Merge lp:~mvo/ubuntu-release-upgrader/lp1071388 into lp:ubuntu-release-upgrader

Proposed by Michael Vogt on 2012-11-05
Status: Merged
Approved by: Barry Warsaw on 2012-11-14
Approved revision: 2587
Merged at revision: 2595
Proposed branch: lp:~mvo/ubuntu-release-upgrader/lp1071388
Merge into: lp:ubuntu-release-upgrader
Diff against target: 147 lines (+37/-10)
3 files modified
DistUpgrade/DistUpgradeView.py (+9/-2)
DistUpgrade/DistUpgradeViewText.py (+16/-8)
tests/test_view.py (+12/-0)
To merge this branch: bzr merge lp:~mvo/ubuntu-release-upgrader/lp1071388
Reviewer Review Type Date Requested Status
Barry Warsaw 2012-11-05 Pending
Review via email: mp+132851@code.launchpad.net

Description of the Change

This should fix the encoding issue in LP: #1068389 when the users enters non-ascii answers in the text view.

To post a comment you must log in.
Michael Vogt (mvo) wrote :

This also needs backporting to the quantal version of the release upgrader.

Barry Warsaw (barry) wrote :

A couple of quick thoughts: you might want to use "utf-8" instead of "utf8". It doesn't matter in practice, but better matches what getpreferredencoding() returns. Very minor nit.

Also, in Python 3, we're generally calling subprocess.Popen(..., universal_newlines=True) now so that you can send unicode to the subprocess instead of bytes. That may avoid a call to .encode() below.

http://docs.python.org/3/library/subprocess.html#frequently-used-arguments

decoding the results of sys.stdin.readline() also looks a bit suspect to me, since that should already return str instead of bytes. Are you sure that works? See also `python3 -h` and the PYTHONIOENCODING envar.

Michael Vogt (mvo) wrote :

On Wed, Nov 07, 2012 at 08:47:18PM -0000, Barry Warsaw wrote:
> A couple of quick thoughts: you might want to use "utf-8" instead of "utf8". It doesn't matter in practice, but better matches what getpreferredencoding() returns. Very minor nit.

Thanks, I fixed that.

> Also, in Python 3, we're generally calling subprocess.Popen(..., universal_newlines=True) now so that you can send unicode to the subprocess instead of bytes. That may avoid a call to .encode() below.
>
> http://docs.python.org/3/library/subprocess.html#frequently-used-arguments

Thanks, I will have to look in more details, but afaict this is also
because we get the data as bytes sometimes.

> decoding the results of sys.stdin.readline() also looks a bit suspect to me, since that should already return str instead of bytes. Are you sure that works? See also `python3 -h` and the PYTHONIOENCODING envar.

This code runs under py2 most of the time as the upgrade needs to be
support back to precise with the default install there. I.e.:
$ python -c 'import sys; print sys.getdefaultencoding()'
ascii

$ python3 -c 'import sys; print(sys.getdefaultencoding())'
utf-8

And it seems like py2 does not honor PYTHONIOENCODING :/

Cheers,
 Michael

Barry Warsaw (barry) wrote :

Michael, have you pushed an update? The diff doesn't look any different.

2588. By Michael Vogt on 2012-11-30

DistUpgrade/DistUpgradeView.py: fix ENCODING

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'DistUpgrade/DistUpgradeView.py'
2--- DistUpgrade/DistUpgradeView.py 2012-10-02 16:53:12 +0000
3+++ DistUpgrade/DistUpgradeView.py 2012-11-30 17:18:23 +0000
4@@ -36,6 +36,14 @@
5 from .DistUpgradeApport import apport_pkgfailure
6
7
8+try:
9+ locale.setlocale(locale.LC_ALL, "")
10+ (code, ENCODING) = locale.getdefaultlocale()
11+except:
12+ logging.exception("getting the encoding failed")
13+ ENCODING = "utf-8" #pyflakes
14+
15+
16 def FuzzyTimeToStr(sec):
17 " return the time a bit fuzzy (no seconds if time > 60 secs "
18 #print("FuzzyTimeToStr: ", sec)
19@@ -373,8 +381,7 @@
20 if downloadSize > 0:
21 downloadSizeStr = apt_pkg.size_to_str(downloadSize)
22 if isinstance(downloadSizeStr, bytes):
23- downloadSizeStr = downloadSizeStr.decode(
24- locale.getpreferredencoding())
25+ downloadSizeStr = downloadSizeStr.decode(ENCODING)
26 msg += _("\n\nYou have to download a total of %s. ") % (
27 downloadSizeStr)
28 msg += self.getAcquireProgress().estimatedDownloadTime(downloadSize)
29
30=== modified file 'DistUpgrade/DistUpgradeViewText.py'
31--- DistUpgrade/DistUpgradeViewText.py 2012-10-19 07:17:35 +0000
32+++ DistUpgrade/DistUpgradeViewText.py 2012-11-30 17:18:23 +0000
33@@ -28,13 +28,19 @@
34 import apt
35 import os
36
37-from .DistUpgradeView import DistUpgradeView, InstallProgress, AcquireProgress
38+from .DistUpgradeView import (
39+ AcquireProgress,
40+ DistUpgradeView,
41+ ENCODING,
42+ InstallProgress,
43+ )
44 import apt.progress
45
46 import gettext
47 from .DistUpgradeGettext import gettext as _
48 from .utils import twrap
49
50+
51 class TextAcquireProgress(AcquireProgress, apt.progress.text.AcquireProgress):
52 def __init__(self):
53 apt.progress.text.AcquireProgress.__init__(self)
54@@ -44,6 +50,7 @@
55 AcquireProgress.pulse(self, owner)
56 return True
57
58+
59 class TextCdromProgressAdapter(apt.progress.base.CdromProgress):
60 """ Report the cdrom add progress """
61 def update(self, text, step):
62@@ -57,7 +64,8 @@
63
64
65 class DistUpgradeViewText(DistUpgradeView):
66- " text frontend of the distUpgrade tool "
67+ """ text frontend of the distUpgrade tool """
68+
69 def __init__(self, datadir=None, logdir=None):
70 # indicate that we benefit from using gnu screen
71 self.needs_screen = True
72@@ -127,7 +135,7 @@
73 if extended_msg:
74 print(twrap(extended_msg))
75 print(_("To continue please press [ENTER]"))
76- sys.stdin.readline()
77+ sys.stdin.readline().decode(ENCODING, "backslashreplace")
78 def error(self, summary, msg, extended_msg=None):
79 print()
80 print(twrap(summary))
81@@ -137,10 +145,10 @@
82 return False
83 def showInPager(self, output):
84 """ helper to show output in a pager """
85- # we need to send a utf8 encode str (bytes in py3) to the pipe
86+ # we need to send a encoded str (bytes in py3) to the pipe
87 # LP: #1068389
88 if not isinstance(output, bytes):
89- output = output.encode("utf-8")
90+ output = output.encode(ENCODING)
91 for pager in ["/usr/bin/sensible-pager", "/bin/more"]:
92 if os.path.exists(pager):
93 p = subprocess.Popen([pager,"-"],stdin=subprocess.PIPE)
94@@ -161,7 +169,7 @@
95 print(" %s %s" % (_("Continue [yN] "), _("Details [d]")), end="")
96 sys.stdout.flush()
97 while True:
98- res = sys.stdin.readline()
99+ res = sys.stdin.readline().decode(ENCODING, "backslashreplace")
100 # TRANSLATORS: the "y" is "yes"
101 if res.strip().lower().startswith(_("y")):
102 return True
103@@ -205,14 +213,14 @@
104 print(twrap(msg))
105 if default == 'No':
106 print(_("Continue [yN] "), end="")
107- res = sys.stdin.readline()
108+ res = sys.stdin.readline().decode(ENCODING, "backslashreplace")
109 # TRANSLATORS: first letter of a positive (yes) answer
110 if res.strip().lower().startswith(_("y")):
111 return True
112 return False
113 else:
114 print(_("Continue [Yn] "), end="")
115- res = sys.stdin.readline()
116+ res = sys.stdin.readline().decode(ENCODING, "backslashreplace")
117 # TRANSLATORS: first letter of a negative (no) answer
118 if res.strip().lower().startswith(_("n")):
119 return False
120
121=== modified file 'tests/test_view.py'
122--- tests/test_view.py 2012-11-09 12:50:59 +0000
123+++ tests/test_view.py 2012-11-30 17:18:23 +0000
124@@ -7,11 +7,23 @@
125 import tempfile
126 import unittest
127
128+from mock import patch
129+
130 from DistUpgrade.DistUpgradeViewText import DistUpgradeViewText
131
132
133 class TestDistUpradeView(unittest.TestCase):
134
135+ def test_prompt_with_unicode_lp1071388(self):
136+ with tempfile.TemporaryFile() as f:
137+ f.write("some unicode: รค".encode("utf-8"))
138+ f.flush()
139+ f.seek(0)
140+ with patch("sys.stdin", f):
141+ v = DistUpgradeViewText()
142+ res = v.askYesNoQuestion("Some text", "some more")
143+ self.assertEqual(res, False)
144+
145 def test_show_in_pager_lp1068389(self):
146 """Regression test for LP: #1068389"""
147 output = tempfile.NamedTemporaryFile()

Subscribers

People subscribed via source and target branches