diff --git a/deluge/common.py b/deluge/common.py index 048d48142..b8f7ff528 100644 --- a/deluge/common.py +++ b/deluge/common.py @@ -241,7 +241,7 @@ def show_file(path, timestamp=None): timestamp = int(time.time()) startup_id = '%s_%u_%s-dbus_TIME%d' % (os.path.basename(sys.argv[0]), os.getpid(), os.uname()[1], timestamp) if DBUS_FILEMAN: - paths = [urlparse.urljoin('file:', urllib.pathname2url(utf8_encoded(path)))] + paths = [urlparse.urljoin('file:', urllib.pathname2url(path))] DBUS_FILEMAN.ShowItems(paths, startup_id, dbus_interface='org.freedesktop.FileManager1') else: env = os.environ.copy() @@ -518,12 +518,16 @@ def parse_human_size(size): if len(tokens) == 1: return int(tokens[0]) # Otherwise we expect to find two tokens: A number and a unit. - if len(tokens) == 2 and isinstance(tokens[1], basestring): - normalized_unit = tokens[1].lower() - # Try to match the first letter of the unit. - for unit in size_units: - if normalized_unit.startswith(unit['prefix'].lower()): - return int(tokens[0] * unit['divider']) + if len(tokens) == 2: + try: + normalized_unit = tokens[1].lower() + except AttributeError: + pass + else: + # Try to match the first letter of the unit. + for unit in size_units: + if normalized_unit.startswith(unit['prefix'].lower()): + return int(tokens[0] * unit['divider']) # We failed to parse the size specification. msg = 'Failed to parse size! (input %r was tokenized as %r)' raise InvalidSize(msg % (size, tokens)) @@ -801,7 +805,7 @@ def decode_bytes(byte_str, encoding='utf8'): """ if not byte_str: return '' - elif isinstance(byte_str, unicode): + elif not isinstance(byte_str, bytes): return byte_str encodings = [lambda: ('utf8', 'strict'), @@ -820,25 +824,6 @@ def decode_bytes(byte_str, encoding='utf8'): return '' -def utf8_encoded(s, encoding='utf8'): - """ - Returns a utf8 encoded string of s - - :param s: (unicode) string to (re-)encode - :type s: basestring - :param encoding: the encoding to use in the decoding - :type encoding: string - :returns: a utf8 encoded string of s - :rtype: str - - """ - if isinstance(s, str): - s = decode_bytes(s, encoding).encode('utf8') - elif isinstance(s, unicode): - s = s.encode('utf8') - return s - - def utf8_encode_structure(data): """Recursively convert all unicode keys and values in a data structure to utf8. @@ -851,14 +836,16 @@ def utf8_encode_structure(data): input type: The data with unicode keys and values converted to utf8. """ - if isinstance(data, unicode): - return data.encode('utf8') - elif isinstance(data, (list, tuple)): + if isinstance(data, (list, tuple)): return type(data)(map(utf8_encode_structure, data)) elif isinstance(data, dict): return dict(map(utf8_encode_structure, data.items())) - else: - return data + elif not isinstance(data, bytes): + try: + return data.encode('utf8') + except AttributeError: + pass + return data @functools.total_ordering @@ -993,7 +980,11 @@ def set_env_variable(name, value): http://sourceforge.net/p/gramps/code/HEAD/tree/branches/maintenance/gramps32/src/TransUtils.py ''' # Update Python's copy of the environment variables - os.environ[name] = value + try: + os.environ[name] = value + except UnicodeEncodeError: + # Python 2 + os.environ[name] = value.encode('utf8') if windows_check(): from ctypes import windll diff --git a/deluge/component.py b/deluge/component.py index 274c86df9..476311410 100644 --- a/deluge/component.py +++ b/deluge/component.py @@ -307,7 +307,7 @@ class ComponentRegistry(object): # Start all the components if names is empty if not names: names = self.components.keys() - elif isinstance(names, basestring): + elif not isinstance(names, (list, tuple)): names = [names] def on_depends_started(result, name): @@ -341,7 +341,7 @@ class ComponentRegistry(object): """ if not names: names = self.components.keys() - elif isinstance(names, basestring): + elif not isinstance(names, (list, tuple)): names = [names] def on_dependents_stopped(result, name): @@ -379,7 +379,7 @@ class ComponentRegistry(object): """ if not names: names = self.components.keys() - elif isinstance(names, basestring): + elif not isinstance(names, (list, tuple)): names = [names] deferreds = [] @@ -405,7 +405,7 @@ class ComponentRegistry(object): """ if not names: names = self.components.keys() - elif isinstance(names, basestring): + elif not isinstance(names, (list, tuple)): names = [names] deferreds = [] diff --git a/deluge/config.py b/deluge/config.py index a5bfa01c0..ae867989a 100644 --- a/deluge/config.py +++ b/deluge/config.py @@ -47,7 +47,7 @@ import logging import os import shutil -from deluge.common import decode_bytes, get_default_config_dir, utf8_encoded +from deluge.common import get_default_config_dir log = logging.getLogger(__name__) callLater = None # Necessary for the config tests @@ -172,8 +172,10 @@ class Config(object): 5 """ - if isinstance(value, basestring): - value = utf8_encoded(value) + try: + value = value.encode('utf8') + except AttributeError: + pass if key not in self.__config: self.__config[key] = value @@ -188,10 +190,7 @@ class Config(object): self.__config[key], type(None)) and not isinstance(self.__config[key], type(value)): try: oldtype = type(self.__config[key]) - if isinstance(self.__config[key], unicode): - value = oldtype(value, 'utf8') - else: - value = oldtype(value) + value = oldtype(value) except ValueError: log.warning('Value Type "%s" invalid for key: %s', type(value), key) raise @@ -244,9 +243,9 @@ class Config(object): 5 """ - if isinstance(self.__config[key], basestring): - return decode_bytes(self.__config[key]) - else: + try: + return self.__config[key].decode('utf8') + except AttributeError: return self.__config[key] def get(self, key, default=None): diff --git a/deluge/core/core.py b/deluge/core/core.py index f0d2eb523..52cacafdf 100644 --- a/deluge/core/core.py +++ b/deluge/core/core.py @@ -710,7 +710,7 @@ class Core(component.Component): if 'owner' in options and not self.core.authmanager.has_account(options['owner']): raise DelugeError('Username "%s" is not known.' % options['owner']) - if isinstance(torrent_ids, basestring): + if not isinstance(torrent_ids, (list, tuple)): torrent_ids = [torrent_ids] for torrent_id in torrent_ids: diff --git a/deluge/core/filtermanager.py b/deluge/core/filtermanager.py index e5c7b936d..7919b0c5e 100644 --- a/deluge/core/filtermanager.py +++ b/deluge/core/filtermanager.py @@ -133,7 +133,7 @@ class FilterManager(component.Component): # Sanitize input: filter-value must be a list of strings for key, value in filter_dict.items(): - if isinstance(value, basestring): + if not isinstance(value, (list, tuple)): filter_dict[key] = [value] # Optimized filter for id diff --git a/deluge/core/torrent.py b/deluge/core/torrent.py index f4b9261fe..66250317e 100644 --- a/deluge/core/torrent.py +++ b/deluge/core/torrent.py @@ -26,7 +26,7 @@ from twisted.internet.defer import Deferred, DeferredList import deluge.component as component from deluge._libtorrent import lt -from deluge.common import decode_bytes, utf8_encoded +from deluge.common import decode_bytes from deluge.configmanager import ConfigManager, get_config_dir from deluge.core.authmanager import AUTH_LEVEL_ADMIN from deluge.decorators import deprecated @@ -1126,12 +1126,12 @@ class Torrent(object): return False try: - # libtorrent needs unicode object if wstrings are enabled, utf8 bytestring otherwise + # lt needs utf8 byte-string. Otherwise if wstrings enabled, unicode string. # Keyword argument flags=2 (dont_replace) dont overwrite target files but delete source. try: - self.handle.move_storage(dest, flags=2) + self.handle.move_storage(dest.encode('utf8'), flags=2) except TypeError: - self.handle.move_storage(utf8_encoded(dest), flags=2) + self.handle.move_storage(dest, flags=2) except RuntimeError as ex: log.error('Error calling libtorrent move_storage: %s', ex) return False @@ -1252,13 +1252,13 @@ class Torrent(object): filenames (list): A list of (index, filename) pairs. """ for index, filename in filenames: - # Make sure filename is a unicode object + # Make sure filename is a sanitized unicode string. filename = sanitize_filepath(decode_bytes(filename)) - # libtorrent needs unicode object if wstrings are enabled, utf8 bytestring otherwise + # lt needs utf8 byte-string. Otherwise if wstrings enabled, unicode string. try: - self.handle.rename_file(index, filename) + self.handle.rename_file(index, filename.encode('utf8')) except TypeError: - self.handle.rename_file(index, utf8_encoded(filename)) + self.handle.rename_file(index, filename) def rename_folder(self, folder, new_folder): """Renames a folder within a torrent. @@ -1292,9 +1292,9 @@ class Torrent(object): ) new_path = _file['path'].replace(folder, new_folder, 1) try: - self.handle.rename_file(_file['index'], new_path) + self.handle.rename_file(_file['index'], new_path.encode('utf8')) except TypeError: - self.handle.rename_file(_file['index'], utf8_encoded(new_path)) + self.handle.rename_file(_file['index'], new_path) def on_folder_rename_complete(dummy_result, torrent, folder, new_folder): """Folder rename complete""" diff --git a/deluge/core/torrentmanager.py b/deluge/core/torrentmanager.py index 81d075117..2233bc4d6 100644 --- a/deluge/core/torrentmanager.py +++ b/deluge/core/torrentmanager.py @@ -24,7 +24,7 @@ from twisted.internet.task import LoopingCall import deluge.component as component from deluge._libtorrent import lt -from deluge.common import decode_bytes, get_magnet_info, utf8_encoded +from deluge.common import decode_bytes, get_magnet_info from deluge.configmanager import ConfigManager, get_config_dir from deluge.core.authmanager import AUTH_LEVEL_ADMIN from deluge.core.torrent import Torrent, TorrentOptions, sanitize_filepath @@ -332,10 +332,9 @@ class TorrentManager(component.Component): add_torrent_params['name'] = name torrent_id = str(torrent_info.info_hash()) elif magnet: - magnet = utf8_encoded(magnet) magnet_info = get_magnet_info(magnet) if magnet_info: - add_torrent_params['url'] = magnet + add_torrent_params['url'] = magnet.encode('utf8') add_torrent_params['name'] = magnet_info['name'] torrent_id = magnet_info['info_hash'] else: @@ -362,9 +361,9 @@ class TorrentManager(component.Component): if log.isEnabledFor(logging.DEBUG): log.debug('renaming file index %s to %s', index, fname) try: - torrent_info.rename_file(index, fname) + torrent_info.rename_file(index, fname.encode('utf8')) except TypeError: - torrent_info.rename_file(index, utf8_encoded(fname)) + torrent_info.rename_file(index, fname) add_torrent_params['ti'] = torrent_info if not options['owner']: @@ -376,7 +375,7 @@ class TorrentManager(component.Component): log.debug('options: %s', options) # Fill in the rest of the add_torrent_params dictionary. - add_torrent_params['save_path'] = utf8_encoded(options['download_location']) + add_torrent_params['save_path'] = options['download_location'].encode('utf8') if options['name']: add_torrent_params['name'] = options['name'] if options['pre_allocate_storage']: diff --git a/deluge/metafile.py b/deluge/metafile.py index 412e62788..1362d5b37 100644 --- a/deluge/metafile.py +++ b/deluge/metafile.py @@ -15,7 +15,6 @@ from __future__ import division, unicode_literals import logging import os.path -import sys import time from hashlib import sha1 as sha @@ -40,22 +39,6 @@ def gmtime(): return time.mktime(time.gmtime()) -def get_filesystem_encoding(): - return sys.getfilesystemencoding() - - -def decode_from_filesystem(path): - encoding = get_filesystem_encoding() - if encoding is None: - assert isinstance(path, unicode), 'Path should be unicode not %s' % type(path) - decoded_path = path - else: - assert isinstance(path, str), 'Path should be str not %s' % type(path) - decoded_path = path.decode(encoding) - - return decoded_path - - def dummy(*v): pass @@ -140,23 +123,6 @@ def calcsize(path): def makeinfo(path, piece_length, progress, name=None, content_type=None, private=False): # HEREDAVE. If path is directory, how do we assign content type? - def to_utf8(name): - if isinstance(name, unicode): - u = name - else: - try: - u = decode_from_filesystem(name) - except Exception: - raise Exception('Could not convert file/directory name %r to ' - 'Unicode. Either the assumed filesystem ' - 'encoding "%s" is wrong or the filename contains ' - 'illegal bytes.' % (name, get_filesystem_encoding())) - - if u.translate(noncharacter_translate) != u: - raise Exception('File/directory name "%s" contains reserved ' - 'unicode values that do not correspond to ' - 'characters.' % name) - return u.encode('utf-8') path = os.path.abspath(path) piece_count = 0 if os.path.isdir(path): @@ -178,7 +144,7 @@ def makeinfo(path, piece_length, progress, name=None, content_type=None, private for p, f in subs: pos = 0 size = os.path.getsize(f) - p2 = [to_utf8(n) for n in p] + p2 = [n.encode('utf8') for n in p] if content_type: fs.append({'length': size, 'path': p2, 'content_type': content_type}) # HEREDAVE. bad for batch! @@ -204,16 +170,13 @@ def makeinfo(path, piece_length, progress, name=None, content_type=None, private piece_count += 1 progress(piece_count, num_pieces) - if name is not None: - assert isinstance(name, unicode) - name = to_utf8(name) - else: - name = to_utf8(os.path.split(path)[1]) + if not name: + name = os.path.split(path)[1] return {'pieces': ''.join(pieces), 'piece length': piece_length, 'files': fs, - 'name': name, + 'name': name.encode('utf8'), 'private': private} else: size = os.path.getsize(path) @@ -234,15 +197,16 @@ def makeinfo(path, piece_length, progress, name=None, content_type=None, private p = size progress(piece_count, num_pieces) h.close() + name = os.path.split(path)[1].encode('utf8') if content_type is not None: return {'pieces': ''.join(pieces), 'piece length': piece_length, 'length': size, - 'name': to_utf8(os.path.split(path)[1]), + 'name': name, 'content_type': content_type, 'private': private} return {'pieces': ''.join(pieces), 'piece length': piece_length, 'length': size, - 'name': to_utf8(os.path.split(path)[1]), + 'name': name, 'private': private} diff --git a/deluge/plugins/AutoAdd/deluge/plugins/autoadd/core.py b/deluge/plugins/AutoAdd/deluge/plugins/autoadd/core.py index 9bfbbb46b..19fa0f2a2 100644 --- a/deluge/plugins/AutoAdd/deluge/plugins/autoadd/core.py +++ b/deluge/plugins/AutoAdd/deluge/plugins/autoadd/core.py @@ -394,8 +394,8 @@ class Core(CorePluginBase): def _make_unicode(self, options): opts = {} for key in options: - if isinstance(options[key], str): - options[key] = unicode(options[key], 'utf8') + if isinstance(options[key], bytes): + options[key] = options[key].decode('utf8') opts[key] = options[key] return opts diff --git a/deluge/plugins/Blocklist/deluge/plugins/blocklist/common.py b/deluge/plugins/Blocklist/deluge/plugins/blocklist/common.py index 05c45a933..5e0a4989f 100644 --- a/deluge/plugins/Blocklist/deluge/plugins/blocklist/common.py +++ b/deluge/plugins/Blocklist/deluge/plugins/blocklist/common.py @@ -145,17 +145,17 @@ class IP(object): # return IP(q1, q2, q3, q4) def __lt__(self, other): - if isinstance(other, basestring): + if isinstance(other, ''.__class__): other = IP.parse(other) return self.long < other.long def __gt__(self, other): - if isinstance(other, basestring): + if isinstance(other, ''.__class__): other = IP.parse(other) return self.long > other.long def __eq__(self, other): - if isinstance(other, basestring): + if isinstance(other, ''.__class__): other = IP.parse(other) return self.long == other.long diff --git a/deluge/plugins/Execute/deluge/plugins/execute/core.py b/deluge/plugins/Execute/deluge/plugins/execute/core.py index 886920d56..5d8ed1591 100644 --- a/deluge/plugins/Execute/deluge/plugins/execute/core.py +++ b/deluge/plugins/Execute/deluge/plugins/execute/core.py @@ -17,7 +17,7 @@ import time from twisted.internet.utils import getProcessOutputAndValue import deluge.component as component -from deluge.common import utf8_encoded, windows_check +from deluge.common import windows_check from deluge.configmanager import ConfigManager from deluge.core.rpcserver import export from deluge.event import DelugeEvent @@ -85,8 +85,7 @@ class Core(CorePluginBase): # Get and store the torrent info before it is removed torrent = component.get('TorrentManager').torrents[torrent_id] info = torrent.get_status(['name', 'download_location']) - self.preremoved_cache[torrent_id] = [utf8_encoded(torrent_id), utf8_encoded(info['name']), - utf8_encoded(info['download_location'])] + self.preremoved_cache[torrent_id] = [torrent_id, info['name'], info['download_location']] def execute_commands(self, torrent_id, event, *arg): if event == 'added' and arg[0]: @@ -99,9 +98,8 @@ class Core(CorePluginBase): info = torrent.get_status(['name', 'download_location']) # Grab the torrent name and download location # getProcessOutputAndValue requires args to be str - torrent_id = utf8_encoded(torrent_id) - torrent_name = utf8_encoded(info['name']) - download_location = utf8_encoded(info['download_location']) + torrent_name = info['name'] + download_location = info['download_location'] log.debug('Running commands for %s', event) @@ -120,7 +118,8 @@ class Core(CorePluginBase): command = os.path.expandvars(command[EXECUTE_COMMAND]) command = os.path.expanduser(command) - cmd_args = [torrent_id, torrent_name, download_location] + cmd_args = [torrent_id.encode('utf8'), torrent_name.encode('utf8'), + download_location.encode('utf8')] if windows_check(): # Escape ampersand on windows (see #2784) cmd_args = [cmd_arg.replace('&', '^^^&') for cmd_arg in cmd_args] diff --git a/deluge/plugins/Notifications/deluge/plugins/notifications/gtkui.py b/deluge/plugins/Notifications/deluge/plugins/notifications/gtkui.py index 829bdbd48..7ff0a725b 100644 --- a/deluge/plugins/Notifications/deluge/plugins/notifications/gtkui.py +++ b/deluge/plugins/Notifications/deluge/plugins/notifications/gtkui.py @@ -151,7 +151,7 @@ class GtkUiNotifications(CustomNotifications): 'handler was: %s' % result) def handle_custom_sound_notification(self, result, eventtype): - if isinstance(result, basestring): + if isinstance(result, ''.__class__): if not result and eventtype in self.config['custom_sounds']: return defer.maybeDeferred( self.__play_sound, self.config['custom_sounds'][eventtype]) diff --git a/deluge/tests/test_config.py b/deluge/tests/test_config.py index 78bfd20b7..6445b305a 100644 --- a/deluge/tests/test_config.py +++ b/deluge/tests/test_config.py @@ -47,7 +47,7 @@ class ConfigTestCase(unittest.TestCase): self.assertEquals(config['unicode'], 'ВИДЕОФИЛЬМЫ') config['unicode'] = b'foostring' - self.assertTrue(isinstance(config.get_item('unicode'), unicode)) + self.assertFalse(isinstance(config.get_item('unicode'), bytes)) config._save_timer.cancel() diff --git a/deluge/tests/test_plugin_metadata.py b/deluge/tests/test_plugin_metadata.py index dafa9d635..63bbb9ab5 100644 --- a/deluge/tests/test_plugin_metadata.py +++ b/deluge/tests/test_plugin_metadata.py @@ -24,7 +24,7 @@ class PluginManagerBaseTestCase(BaseTestCase): pm = PluginManagerBase('core.conf', 'deluge.plugin.core') for p in pm.get_available_plugins(): for key, value in pm.get_plugin_info(p).items(): - self.assertTrue(isinstance('%s: %s' % (key, value), basestring)) + self.assertTrue(isinstance('%s: %s' % (key, value), ''.__class__)) def test_get_plugin_info_invalid_name(self): pm = PluginManagerBase('core.conf', 'deluge.plugin.core') diff --git a/deluge/ui/console/cmdline/commands/info.py b/deluge/ui/console/cmdline/commands/info.py index 84838713f..fc80d1aba 100644 --- a/deluge/ui/console/cmdline/commands/info.py +++ b/deluge/ui/console/cmdline/commands/info.py @@ -212,9 +212,6 @@ class Command(BaseCommand): def tlen(string): return strwidth(format_utils.remove_formatting(string)) - if not isinstance(col_filename, unicode): - col_filename = unicode(col_filename, 'utf-8') - col_all_info = col_size + col_progress + col_priority # Check how much space we've got left after writing all the info space_left = cols - tlen(col_all_info) diff --git a/deluge/ui/console/main.py b/deluge/ui/console/main.py index cce63d662..7b7904c0a 100644 --- a/deluge/ui/console/main.py +++ b/deluge/ui/console/main.py @@ -371,8 +371,7 @@ Please use commands from the command line, e.g.:\n no matches are found. """ - if not isinstance(string, unicode): - string = unicode(string, self.encoding) + deluge.common.decode_bytes(string, self.encoding) if string == '*' or string == '': return [tid for tid, name in self.torrents] @@ -387,8 +386,7 @@ Please use commands from the command line, e.g.:\n matches = [] for tid, name in self.torrents: - if not isinstance(name, unicode): - name = unicode(name, self.encoding) + deluge.common.decode_bytes(name, self.encoding) if getattr(tid, match_func, None)(string) or getattr(name, match_func, None)(string): matches.append(tid) return matches @@ -423,7 +421,7 @@ Please use commands from the command line, e.g.:\n component.get('CmdLine').add_line(s, False) self.events.append(s) else: - print(colors.strip_colors(deluge.common.utf8_encoded(s))) + print(colors.strip_colors(s.encode('utf8'))) def write_event(self, s): if self.interactive: @@ -434,7 +432,7 @@ Please use commands from the command line, e.g.:\n component.get('CmdLine').add_line(s, False) self.events.append(s) else: - print(colors.strip_colors(deluge.common.utf8_encoded(s))) + print(colors.strip_colors(s.encode('utf8'))) def _migrate_config_1_to_2(self, config): """Create better structure by moving most settings out of dict root diff --git a/deluge/ui/console/modes/cmdline.py b/deluge/ui/console/modes/cmdline.py index 0eb134e6c..287791a52 100644 --- a/deluge/ui/console/modes/cmdline.py +++ b/deluge/ui/console/modes/cmdline.py @@ -417,10 +417,7 @@ class CmdLine(BaseMode, Commander): # Write the line with open(self.history_file[active_file], 'a', encoding='utf8') as _file: - if isinstance(text, unicode): - text = text.encode(self.encoding) - _file.write(text) - _file.write(os.linesep) + _file.write(text + '\n') # And increment line counter self._hf_lines[active_file] += 1 diff --git a/deluge/ui/console/modes/torrentlist/torrentactions.py b/deluge/ui/console/modes/torrentlist/torrentactions.py index d855aaa95..404d2c27d 100644 --- a/deluge/ui/console/modes/torrentlist/torrentactions.py +++ b/deluge/ui/console/modes/torrentlist/torrentactions.py @@ -131,17 +131,14 @@ def action_torrent_info(mode=None, torrent_ids=None, **kwargs): for field in torrent_options: caption = '{!info!}' + TORRENT_DATA_FIELD[field]['name'] value = options[field] - field_type = type(value) - if field_type in [str, unicode]: - if not isinstance(value, basestring): - value = str(value) + if isinstance(value, ''.__class__): option_popup.add_text_input(field, caption, value) - elif field_type == bool: - choices = (['Yes', 'No'], [True, False], [True, False].index(options[field])) + elif isinstance(value, bool): + choices = (['Yes', 'No'], [True, False], [True, False].index(value)) option_popup.add_select_input(field, caption, choices[0], choices[1], choices[2]) - elif field_type == float: + elif isinstance(value, float): option_popup.add_float_spin_input(field, caption, value=value, min_val=-1) - elif field_type == int: + elif isinstance(value, int): option_popup.add_int_spin_input(field, caption, value=value, min_val=-1) mode.push_popup(option_popup) diff --git a/deluge/ui/console/modes/torrentlist/torrentview.py b/deluge/ui/console/modes/torrentlist/torrentview.py index 98b18f1ec..6ef1d7e83 100644 --- a/deluge/ui/console/modes/torrentlist/torrentview.py +++ b/deluge/ui/console/modes/torrentlist/torrentview.py @@ -237,18 +237,15 @@ class TorrentView(InputKeyHandler): # and if it's a string first_element = state[state.keys()[0]] if field in first_element: - is_string = isinstance(first_element[field], basestring) - def sort_key(s): - return state.get(s)[field] + try: + # Sort case-insensitively but preserve A>a order. + return state.get(s)[field].lower() + except AttributeError: + # Not a string. + return state.get(s)[field] - def sort_key2(s): - return state.get(s)[field].lower() - - # If it's a string, sort case-insensitively but preserve A>a order to_sort = sorted(to_sort, _queue_sort, sort_key, reverse) - if is_string: - to_sort = sorted(to_sort, _queue_sort, sort_key2, reverse) if field == 'eta': to_sort = sorted(to_sort, key=lambda s: state.get(s)['eta'] == 0) diff --git a/deluge/ui/console/utils/colors.py b/deluge/ui/console/utils/colors.py index 50ec6d40c..17119e71a 100644 --- a/deluge/ui/console/utils/colors.py +++ b/deluge/ui/console/utils/colors.py @@ -131,7 +131,7 @@ def strip_colors(line): return line -def get_line_length(line, encoding='UTF-8'): +def get_line_length(line): """ Returns the string length without the color formatting. @@ -139,9 +139,6 @@ def get_line_length(line, encoding='UTF-8'): if line.count('{!') != line.count('!}'): raise BadColorString('Number of {! is not equal to number of !}') - if isinstance(line, unicode): - line = line.encode(encoding, 'replace') - # Remove all the color tags line = strip_colors(line) @@ -150,7 +147,7 @@ def get_line_length(line, encoding='UTF-8'): return len(line) -def get_line_width(line, encoding='UTF-8'): +def get_line_width(line): """ Get width of string considering double width characters @@ -158,9 +155,6 @@ def get_line_width(line, encoding='UTF-8'): if line.count('{!') != line.count('!}'): raise BadColorString('Number of {! is not equal to number of !}') - if isinstance(line, unicode): - line = line.encode(encoding, 'replace') - # Remove all the color tags line = strip_colors(line) @@ -180,9 +174,6 @@ def parse_color_string(s, encoding='UTF-8'): if s.count('{!') != s.count('!}'): raise BadColorString('Number of {! is not equal to number of !}') - if isinstance(s, unicode): - s = s.encode(encoding, 'replace') - ret = [] last_color_attr = None # Keep track of where the strings diff --git a/deluge/ui/console/utils/format_utils.py b/deluge/ui/console/utils/format_utils.py index f259061d6..ac7fc2539 100644 --- a/deluge/ui/console/utils/format_utils.py +++ b/deluge/ui/console/utils/format_utils.py @@ -11,8 +11,7 @@ from __future__ import unicode_literals import re from collections import deque -from unicodedata import normalize as ud_normalize -from unicodedata import east_asian_width +from unicodedata import east_asian_width, normalize import deluge.common from deluge.ui.common import FILE_PRIORITY @@ -88,7 +87,7 @@ def trim_string(string, w, have_dbls): idx = 0 while width < w: chrs.append(string[idx]) - if east_asian_width(string[idx]) in ['W', 'F']: + if east_asian_width(string[idx]) in 'WF': width += 2 else: width += 1 @@ -102,14 +101,13 @@ def trim_string(string, w, have_dbls): def format_column(col, lim): - dbls = 0 - # Chosen over isinstance(col, unicode) and col.__class__ == unicode - # for speed - it's ~3 times faster for non-unicode strings and ~1.5 - # for unicode strings. - if col.__class__ is unicode: + try: # might have some double width chars - col = ud_normalize('NFC', col) + col = normalize('NFC', col) dbls = sum(east_asian_width(c) in 'WF' for c in col) + except TypeError: + dbls = 0 + size = len(col) + dbls if size >= lim - 1: return trim_string(col, lim, dbls > 0) @@ -239,8 +237,6 @@ def strwidth(string): """ Measure width of a string considering asian double width characters """ - if not isinstance(string, unicode): - string = unicode(string, 'utf-8') return sum([1 + (east_asian_width(char) in ['W', 'F']) for char in string]) diff --git a/deluge/ui/console/widgets/inputpane.py b/deluge/ui/console/widgets/inputpane.py index e76708f21..cf53b48ea 100644 --- a/deluge/ui/console/widgets/inputpane.py +++ b/deluge/ui/console/widgets/inputpane.py @@ -299,7 +299,7 @@ class BaseInputPane(InputKeyHandler): if ipt.default_col != -1: default_col = int(ipt.default_col) - if isinstance(ipt.default_col, basestring) and ipt.default_col[0] in ['+', '-']: + if isinstance(ipt.default_col, ''.__class__) and ipt.default_col[0] in ['+', '-']: col += default_col cursor_offset += default_col field_width -= default_col # Increase to col must be reflected here diff --git a/deluge/ui/gtkui/listview.py b/deluge/ui/gtkui/listview.py index e61162a6f..2b3f7b1e5 100644 --- a/deluge/ui/gtkui/listview.py +++ b/deluge/ui/gtkui/listview.py @@ -15,6 +15,7 @@ import gtk from gobject import SIGNAL_RUN_LAST, TYPE_NONE, signal_new from gtk.gdk import Event # pylint: disable=ungrouped-imports +from deluge.common import decode_bytes from deluge.ui.gtkui.common import load_pickled_state_file, save_pickled_state_file signal_new('button-press-event', gtk.TreeViewColumn, SIGNAL_RUN_LAST, TYPE_NONE, (Event,)) @@ -320,7 +321,7 @@ class ListView(object): try: self.columns[name].column.set_visible(widget.get_active()) except KeyError: - self.columns[unicode(name)].column.set_visible(widget.get_active()) + self.columns[decode_bytes(name)].column.set_visible(widget.get_active()) return def on_treeview_header_right_clicked(self, column, event): diff --git a/deluge/ui/gtkui/preferences.py b/deluge/ui/gtkui/preferences.py index ab5954cc7..2e424549c 100644 --- a/deluge/ui/gtkui/preferences.py +++ b/deluge/ui/gtkui/preferences.py @@ -401,20 +401,20 @@ class Preferences(component.Component): # Update the widgets accordingly for key in core_widgets: modifier = core_widgets[key][0] - if isinstance(key, basestring): + try: widget = self.builder.get_object(key) - else: + except TypeError: widget = key widget.set_sensitive(self.is_connected) if self.is_connected: value = core_widgets[key][1] - from types import FunctionType - if isinstance(value, FunctionType): - value = value() - elif isinstance(value, basestring): + try: value = self.core_config[value] + except KeyError: + if callable(value): + value = value() elif modifier: value = {'active': False, 'not_active': False, 'value': 0, 'text': '', 'path_chooser': ''}[modifier] @@ -433,9 +433,9 @@ class Preferences(component.Component): if self.is_connected: for key in core_widgets: - if isinstance(key, basestring): + try: widget = self.builder.get_object(key) - else: + except TypeError: widget = key # Update the toggle status if necessary self.on_toggle(widget) diff --git a/deluge/ui/translations_util.py b/deluge/ui/translations_util.py index 6803d55a2..656cabd1c 100644 --- a/deluge/ui/translations_util.py +++ b/deluge/ui/translations_util.py @@ -70,7 +70,6 @@ def set_language(lang): :param lang: the language, e.g. "en", "de" or "en_GB" :type lang: str """ - lang = str(lang) # Necessary to set these environment variables for GtkBuilder deluge.common.set_env_variable('LANGUAGE', lang) # Windows/Linux deluge.common.set_env_variable('LANG', lang) # For OSX diff --git a/deluge/ui/web/auth.py b/deluge/ui/web/auth.py index be862a11d..d5a439d42 100644 --- a/deluge/ui/web/auth.py +++ b/deluge/ui/web/auth.py @@ -18,8 +18,6 @@ from email.utils import formatdate from twisted.internet.task import LoopingCall -from deluge.common import utf8_encoded - log = logging.getLogger(__name__) @@ -143,7 +141,7 @@ class Auth(JSONComponent): log.debug('Received a password via the 1.2-dev auth method') m = hashlib.md5() m.update(config['pwd_salt']) - m.update(utf8_encoded(password)) + m.update(password.encode('utf8')) if m.hexdigest() == config['pwd_md5']: # We want to move the password over to sha1 and remove # the old passwords from the config file. @@ -163,7 +161,7 @@ class Auth(JSONComponent): from base64 import decodestring m = hashlib.md5() m.update(decodestring(config['old_pwd_salt'])) - m.update(utf8_encoded(password)) + m.update(password.encode('utf8')) if m.digest() == decodestring(config['old_pwd_md5']): # We want to move the password over to sha1 and remove @@ -179,7 +177,7 @@ class Auth(JSONComponent): log.debug('Received a password via the 1.2 auth method') s = hashlib.sha1() s.update(config['pwd_salt']) - s.update(utf8_encoded(password)) + s.update(password.encode('utf8')) if s.hexdigest() == config['pwd_sha1']: return True @@ -249,7 +247,7 @@ class Auth(JSONComponent): log.debug('Changing password') salt = hashlib.sha1(os.urandom(32)).hexdigest() s = hashlib.sha1(salt) - s.update(utf8_encoded(new_password)) + s.update(new_password.encode('utf8')) self.config['pwd_salt'] = salt self.config['pwd_sha1'] = s.hexdigest() return True diff --git a/deluge/ui/web/json_api.py b/deluge/ui/web/json_api.py index 96cf80aaf..0e66408c8 100644 --- a/deluge/ui/web/json_api.py +++ b/deluge/ui/web/json_api.py @@ -897,8 +897,6 @@ class WebApi(JSONComponent): if key in ['sessions', 'pwd_salt', 'pwd_sha1']: log.warn('Ignored attempt to overwrite web config key: %s', key) continue - if isinstance(config[key], basestring): - config[key] = config[key].encode('utf8') web_config[key] = config[key] @export