[master 26/30] Add and use function that makes sure we work with strings (#1014220)
M4rtinK
installerbot-noreply at redhat.com
Mon Jun 1 14:04:43 UTC 2015
From: Vratislav Podzimek <vpodzime at redhat.com>
This is useful in many places where we are never sure if we get str or bytes and
we need/want to work with str objects.
Also remove one related (previously) unused import and obsolete comment
& needless encoding.
---
pyanaconda/iutil.py | 48 ++++++++++++++++++++++++++++--------
pyanaconda/localization.py | 3 +--
pyanaconda/ui/tui/simpleline/base.py | 32 ++++++++++--------------
3 files changed, 52 insertions(+), 31 deletions(-)
diff --git a/pyanaconda/iutil.py b/pyanaconda/iutil.py
index 8b0f06a..1d50ab6 100644
--- a/pyanaconda/iutil.py
+++ b/pyanaconda/iutil.py
@@ -30,7 +30,6 @@
# Used for ascii_lowercase, ascii_uppercase constants
import string # pylint: disable=deprecated-module
import tempfile
-import types
import re
from urllib import quote, unquote
import gettext
@@ -1079,13 +1078,34 @@ def is_unsupported_hw():
log.debug("Installing on Unsupported Hardware")
return status
+def ensure_str(str_or_bytes, keep_none=True):
+ """
+ Returns a str instance for given string or None if requested to keep it.
+
+ :param str_or_bytes: string to be kept or converted to str type
+ :type str_or_bytes: str or bytes
+ :param bool keep_none: whether to keep None as it is or raise ValueError if
+ None is passed
+ :raises ValueError: if applied on an object not being of type bytes nor str
+ (nor NoneType if :param:`keep_none` is False)
+ """
+
+ if keep_none and str_or_bytes is None:
+ return None
+ elif isinstance(str_or_bytes, str):
+ return str_or_bytes
+ elif isinstance(str_or_bytes, bytes):
+ return str_or_bytes.decode(sys.getdefaultencoding())
+ else:
+ raise ValueError("str_or_bytes must be of type 'str' or 'bytes', not '%s'" % type(str_or_bytes))
+
# Define translations between ASCII uppercase and lowercase for
# locale-independent string conversions. The tables are 256-byte string used
# with str.translate. If str.translate is used with a unicode string,
# even if the string contains only 7-bit characters, str.translate will
# raise a UnicodeDecodeError.
-_ASCIIupper_table = string.maketrans(string.ascii_lowercase, string.ascii_uppercase)
-_ASCIIlower_table = string.maketrans(string.ascii_uppercase, string.ascii_lowercase)
+_ASCIIlower_table = str.maketrans(string.ascii_uppercase, string.ascii_lowercase)
+_ASCIIupper_table = str.maketrans(string.ascii_lowercase, string.ascii_uppercase)
def _toASCII(s):
"""Convert a unicode string to ASCII"""
@@ -1106,7 +1126,12 @@ def upperASCII(s):
The returned string will contain only ASCII characters. This function is
locale-independent.
"""
- return string.translate(_toASCII(s), _ASCIIupper_table)
+
+ # XXX: Python 3 has str.maketrans() and bytes.maketrans() so we should
+ # ideally use one or the other depending on the type of 's'. But it turns
+ # out we expect this function to always return string even if given bytes.
+ s = ensure_str(s)
+ return str.translate(_toASCII(s), _ASCIIupper_table)
def lowerASCII(s):
"""Convert a string to lowercase using only ASCII character definitions.
@@ -1114,7 +1139,12 @@ def lowerASCII(s):
The returned string will contain only ASCII characters. This function is
locale-independent.
"""
- return string.translate(_toASCII(s), _ASCIIlower_table)
+
+ # XXX: Python 3 has str.maketrans() and bytes.maketrans() so we should
+ # ideally use one or the other depending on the type of 's'. But it turns
+ # out we expect this function to always return string even if given bytes.
+ s = ensure_str(s)
+ return str.translate(_toASCII(s), _ASCIIlower_table)
def upcase_first_letter(text):
"""
@@ -1158,11 +1188,9 @@ def have_word_match(str1, str2):
# non-empty string cannot be found in an empty string
return False
- # Convert both arguments to unicode if not already
- if isinstance(str1, str):
- str1 = str1.decode('utf-8')
- if isinstance(str2, str):
- str2 = str2.decode('utf-8')
+ # Convert both arguments to string if not already
+ str1 = ensure_str(str1)
+ str2 = ensure_str(str2)
str1 = str1.lower()
str1_words = str1.split()
diff --git a/pyanaconda/localization.py b/pyanaconda/localization.py
index 9a28837..1613f48 100644
--- a/pyanaconda/localization.py
+++ b/pyanaconda/localization.py
@@ -397,8 +397,7 @@ def get_xlated_timezone(tz_spec_part):
xlated = langtable.timezone_name(tz_spec_part, languageIdQuery=parts["language"],
territoryIdQuery=parts.get("territory", ""),
scriptIdQuery=parts.get("script", ""))
-
- return xlated.encode("utf-8")
+ return xlated
def write_language_configuration(lang, root):
"""
diff --git a/pyanaconda/ui/tui/simpleline/base.py b/pyanaconda/ui/tui/simpleline/base.py
index 211b60e..9fec160 100644
--- a/pyanaconda/ui/tui/simpleline/base.py
+++ b/pyanaconda/ui/tui/simpleline/base.py
@@ -72,7 +72,7 @@ def __init__(self, title, yes_or_no_question=None, width=80, queue_instance=None
quit_message=None):
"""
:param title: application title for whenever we need to display app name
- :type title: unicode
+ :type title: str
:param yes_or_no_question: UIScreen object class used for Quit dialog
:type yes_or_no_question: class UIScreen accepting additional message arg
@@ -428,7 +428,7 @@ def input(self, args, key):
:type args: anything
:param key: the string entered by user
- :type key: unicode
+ :type key: str
:return: True if key was processed, False if it was not recognized
:rtype: True|False
@@ -582,11 +582,11 @@ def show_all(self):
w.render(self.app.width)
if isinstance(w, Widget):
self._print_long_widget(w)
- elif isinstance(w, types.StringType):
- print(w.decode("utf-8"))
+ elif type(w) == bytes:
+ print(w)
else:
- # not a widget, just print its unicode representation
- print(unicode(w))
+ # not a widget or string, just print its string representation
+ print(str(w))
show = show_all
def hide(self):
@@ -597,7 +597,7 @@ def input(self, args, key):
"""Method called to process input. If the input is not handled here, return it.
:param key: input string to process
- :type key: unicode
+ :type key: str
:param args: optional argument passed from switch_screen calls
:type args: anything
@@ -605,7 +605,7 @@ def input(self, args, key):
:return: return True or INPUT_PROCESSED (None) if key was handled,
INPUT_DISCARDED (False) if the screen should not process input
on the App and key if you want it to.
- :rtype: True|False|None|unicode
+ :rtype: True|False|None|str
"""
return key
@@ -618,7 +618,7 @@ def prompt(self, args=None):
:return: returns text to be shown next to the prompt for input or None
to skip further input processing
- :rtype: unicode|None
+ :rtype: str|None
"""
return _(u" Please make your choice from above ['q' to quit | 'c' to continue |\n 'r' to refresh]: ")
@@ -684,10 +684,10 @@ def get_lines(self):
"""Get lines to write out in order to show this widget.
:return: lines representing this widget
- :rtype: list(unicode)
+ :rtype: list(str)
"""
- return [unicode(u"".join(line)) for line in self._buffer]
+ return [str(u"".join(line)) for line in self._buffer]
def setxy(self, row, col):
"""Sets cursor position.
@@ -755,7 +755,7 @@ def write(self, text, row=None, col=None, width=None, block=False):
"""This method emulates typing machine writing to this widget's buffer.
:param text: text to type
- :type text: unicode
+ :type text: str
:param row: row number to start at (default is at the cursor position)
:type row: int
@@ -772,13 +772,7 @@ def write(self, text, row=None, col=None, width=None, block=False):
if not text:
return
- if isinstance(text, str):
- try:
- text = text.decode("utf-8")
- except UnicodeDecodeError as e:
- raise ValueError("Unable to decode string %s" %
- str(e.object).decode("utf-8", "replace"))
-
+ text = iutil.ensure_str(text)
if row is None:
row = self._cursor[0]
--
To view this commit on github, visit https://github.com/rhinstaller/anaconda/commit/0f69039154ab2c1db5ed06ba8f76368483d3b246
More information about the anaconda-patches
mailing list