[Py2to3] Large set of changes for Python 3 compat

- Preparation work for using six or future module for Py2/3 compat. The
   code will be written in Python 3 with Python 2 fallbacks.
 - Added some Py3 imports with Py2 fallbacks to make it easier to remove
   Py2 code in future.
 - Replace xrange with range (sort out import as top of files in future).
 - Workaround Py2to3 basestring issue with inline if in instances. This means
   every usage of basestring is more considered.
 - Replace iteritems and itervalues for items and values. There might be a
   performance penalty on Py2 so might need to revisit this change.
This commit is contained in:
Calum Lind 2017-02-24 18:28:33 +00:00
parent 321677e05a
commit eb38e0ffff
64 changed files with 230 additions and 198 deletions

View file

@ -21,14 +21,20 @@ import re
import subprocess
import sys
import time
import urllib
import urlparse
import chardet
import pkg_resources
from deluge.error import InvalidPathError
try:
from urllib.parse import unquote_plus, urljoin
from urllib.request import pathname2url
except ImportError:
# PY2 fallback
from urlparse import urljoin # pylint: disable=ungrouped-imports
from urllib import pathname2url, unquote_plus # pylint: disable=ungrouped-imports
DBUS_FILEMAN = None
# gi makes dbus available on Window but don't import it as unused.
if platform.system() not in ('Windows', 'Microsoft', 'Darwin'):
@ -56,6 +62,8 @@ TORRENT_STATE = [
'Moving'
]
PY2 = sys.version_info.major == 2
def get_version():
"""
@ -82,12 +90,16 @@ def get_default_config_dir(filename=None):
def save_config_path(resource):
app_data_path = os.environ.get('APPDATA')
if not app_data_path:
import _winreg
hkey = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,
'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders')
app_data_reg = _winreg.QueryValueEx(hkey, 'AppData')
try:
import winreg
except ImportError:
import _winreg as winreg # For Python 2.
hkey = winreg.OpenKey(
winreg.HKEY_CURRENT_USER,
'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders')
app_data_reg = winreg.QueryValueEx(hkey, 'AppData')
app_data_path = app_data_reg[0]
_winreg.CloseKey(hkey)
winreg.CloseKey(hkey)
return os.path.join(app_data_path, resource)
else:
from xdg.BaseDirectory import save_config_path
@ -241,7 +253,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(path))]
paths = [urljoin('file:', pathname2url(path))]
DBUS_FILEMAN.ShowItems(paths, startup_id, dbus_interface='org.freedesktop.FileManager1')
else:
env = os.environ.copy()
@ -626,7 +638,7 @@ def get_magnet_info(uri):
else:
break
elif param.startswith(dn_param):
name = urllib.unquote_plus(param[len(dn_param):])
name = unquote_plus(param[len(dn_param):])
if info_hash:
if not name:
@ -837,9 +849,9 @@ def utf8_encode_structure(data):
"""
if isinstance(data, (list, tuple)):
return type(data)(map(utf8_encode_structure, data))
return type(data)([utf8_encode_structure(d) for d in data])
elif isinstance(data, dict):
return dict(map(utf8_encode_structure, data.items()))
return dict([utf8_encode_structure(d) for d in data.items()])
elif not isinstance(data, bytes):
try:
return data.encode('utf8')
@ -1048,7 +1060,7 @@ def unicode_argv():
# Remove Python executable and commands if present
start = argc.value - len(sys.argv)
return [argv[i] for i in
xrange(start, argc.value)]
range(start, argc.value)]
else:
# On other platforms, we have to find the likely encoding of the args and decode
# First check if sys.stdout or stdin have encoding set

View file

@ -17,6 +17,8 @@ from twisted.internet import reactor
from twisted.internet.defer import DeferredList, fail, maybeDeferred, succeed
from twisted.internet.task import LoopingCall, deferLater
from deluge.common import PY2
log = logging.getLogger(__name__)
@ -307,7 +309,7 @@ class ComponentRegistry(object):
# Start all the components if names is empty
if not names:
names = self.components.keys()
elif not isinstance(names, (list, tuple)):
elif isinstance(names, str if not PY2 else basestring):
names = [names]
def on_depends_started(result, name):
@ -341,7 +343,7 @@ class ComponentRegistry(object):
"""
if not names:
names = self.components.keys()
elif not isinstance(names, (list, tuple)):
elif isinstance(names, str if not PY2 else basestring):
names = [names]
def on_dependents_stopped(result, name):
@ -379,7 +381,7 @@ class ComponentRegistry(object):
"""
if not names:
names = self.components.keys()
elif not isinstance(names, (list, tuple)):
elif isinstance(names, str if not PY2 else basestring):
names = [names]
deferreds = []
@ -405,7 +407,7 @@ class ComponentRegistry(object):
"""
if not names:
names = self.components.keys()
elif not isinstance(names, (list, tuple)):
elif isinstance(names, str if not PY2 else basestring):
names = [names]
deferreds = []
@ -429,7 +431,7 @@ class ComponentRegistry(object):
def on_stopped(result):
return DeferredList([comp._component_shutdown() for comp in self.components.values()])
return self.stop(self.components.keys()).addCallback(on_stopped)
return self.stop(list(self.components.keys())).addCallback(on_stopped)
def update(self):
"""Update all Components that are in a Started state."""

View file

@ -129,7 +129,7 @@ class Config(object):
self._save_timer = None
if defaults:
for key, value in defaults.iteritems():
for key, value in defaults.items():
self.set_item(key, value)
# Load the config from file in the config_dir
@ -367,7 +367,7 @@ class Config(object):
"""
log.debug('Calling all set functions..')
for key, value in self.__set_functions.iteritems():
for key, value in self.__set_functions.items():
for func in value:
func(key, self.__config[key])

View file

@ -90,7 +90,7 @@ class _ConfigManager(object):
"""Get a reference to the Config object for this filename"""
log.debug('Getting config: %s', config_file)
# Create the config object if not already created
if config_file not in self.config_files.keys():
if config_file not in self.config_files:
self.config_files[config_file] = Config(config_file, defaults,
config_dir=self.config_directory,
file_version=file_version)

View file

@ -27,12 +27,8 @@ AUTH_LEVELS_MAPPING = {
'READONLY': AUTH_LEVEL_READONLY,
'DEFAULT': AUTH_LEVEL_NORMAL,
'NORMAL': AUTH_LEVEL_DEFAULT,
'ADMIN': AUTH_LEVEL_ADMIN
}
AUTH_LEVELS_MAPPING_REVERSE = {}
for key, value in AUTH_LEVELS_MAPPING.iteritems():
AUTH_LEVELS_MAPPING_REVERSE[value] = key
'ADMIN': AUTH_LEVEL_ADMIN}
AUTH_LEVELS_MAPPING_REVERSE = {v: k for k, v in AUTH_LEVELS_MAPPING.items()}
class Account(object):

View file

@ -25,6 +25,7 @@ import deluge.common
import deluge.component as component
from deluge import path_chooser_common
from deluge._libtorrent import lt
from deluge.common import PY2
from deluge.configmanager import ConfigManager, get_config_dir
from deluge.core.alertmanager import AlertManager
from deluge.core.authmanager import (AUTH_LEVEL_ADMIN, AUTH_LEVEL_NONE, AUTH_LEVELS_MAPPING,
@ -40,6 +41,12 @@ from deluge.error import AddTorrentError, DelugeError, InvalidPathError, Invalid
from deluge.event import NewVersionAvailableEvent, SessionPausedEvent, SessionResumedEvent, TorrentQueueChangedEvent
from deluge.httpdownloader import download_file
try:
from urllib.request import urlopen, URLError
except ImportError:
# PY2 fallback
from urllib2 import urlopen, URLError
log = logging.getLogger(__name__)
OLD_SESSION_STATUS_KEYS = {
@ -293,7 +300,6 @@ class Core(component.Component):
def get_new_release(self):
log.debug('get_new_release')
from urllib2 import urlopen, URLError
try:
self.new_release = urlopen('http://download.deluge-torrent.org/version-1.0').read().strip()
except URLError as ex:
@ -596,7 +602,7 @@ class Core(component.Component):
status_dict, plugin_keys = args
# Ask the plugin manager to fill in the plugin keys
if len(plugin_keys) > 0:
for key in status_dict.keys():
for key in status_dict:
status_dict[key].update(self.pluginmanager.get_status(key, plugin_keys))
return status_dict
d.addCallback(add_plugin_fields)
@ -635,7 +641,7 @@ class Core(component.Component):
def set_config(self, config):
"""Set the config with values from dictionary"""
# Load all the values into the configuration
for key in config.keys():
for key in config:
if self.read_only_config_keys and key in self.read_only_config_keys:
continue
self.config[key] = config[key]
@ -710,7 +716,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 not isinstance(torrent_ids, (list, tuple)):
if isinstance(torrent_ids, str if not PY2 else basestring):
torrent_ids = [torrent_ids]
for torrent_id in torrent_ids:

View file

@ -12,7 +12,7 @@ from __future__ import unicode_literals
import logging
import deluge.component as component
from deluge.common import TORRENT_STATE
from deluge.common import PY2, TORRENT_STATE
log = logging.getLogger(__name__)
@ -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 not isinstance(value, (list, tuple)):
if isinstance(value, str if not PY2 else basestring):
filter_dict[key] = [value]
# Optimized filter for id
@ -171,11 +171,11 @@ class FilterManager(component.Component):
if not filter_dict:
return torrent_ids
torrent_keys, plugin_keys = self.torrents.separate_keys(filter_dict.keys(), torrent_ids)
torrent_keys, plugin_keys = self.torrents.separate_keys(list(filter_dict), torrent_ids)
# Leftover filter arguments, default filter on status fields.
for torrent_id in list(torrent_ids):
status = self.core.create_torrent_status(torrent_id, torrent_keys, plugin_keys)
for field, values in filter_dict.iteritems():
for field, values in filter_dict.items():
if field in status and status[field] in values:
continue
elif torrent_id in torrent_ids:
@ -212,9 +212,7 @@ class FilterManager(component.Component):
self._hide_state_items(items[cat])
# Return a dict of tuples:
sorted_items = {}
for field in tree_keys:
sorted_items[field] = sorted(items[field].iteritems())
sorted_items = {field: sorted(items[field].items()) for field in tree_keys}
if 'state' in tree_keys:
sorted_items['state'].sort(self._sort_state_items)

View file

@ -12,6 +12,7 @@ from __future__ import unicode_literals
import logging
import os
import platform
import random
import threading
@ -28,6 +29,13 @@ try:
except ImportError:
GeoIP = None
try:
from urllib.parse import quote_plus
from urllib.request import urlopen
except ImportError:
from urllib import quote_plus
from urllib2 import urlopen
log = logging.getLogger(__name__)
DEFAULT_PREFS = {
@ -322,9 +330,6 @@ class PreferencesManager(component.Component):
now = time.time()
# check if we've done this within the last week or never
if (now - self.config['info_sent']) >= (60 * 60 * 24 * 7):
from urllib import quote_plus
from urllib2 import urlopen
import platform
try:
url = 'http://deluge-torrent.org/stats_get.php?processor=' + \
platform.machine() + '&python=' + platform.python_version() \

View file

@ -437,7 +437,7 @@ class RPCServer(component.Component):
:returns: the exported methods
:rtype: list
"""
return self.factory.methods.keys()
return list(self.factory.methods.keys())
def get_session_id(self):
"""

View file

@ -159,7 +159,7 @@ class TorrentOptions(dict):
'stop_ratio': 'stop_seed_ratio',
'super_seeding': 'super_seeding'
}
for opt_k, conf_k in options_conf_map.iteritems():
for opt_k, conf_k in options_conf_map.items():
self[opt_k] = config[conf_k]
self['file_priorities'] = []
self['mapped_files'] = {}
@ -924,7 +924,7 @@ class Torrent(object):
self.update_status(self.handle.status())
if all_keys:
keys = self.status_funcs.keys()
keys = self.status_funcs
status_dict = {}
@ -1307,7 +1307,7 @@ class Torrent(object):
torrent.waiting_on_folder_rename = [_dir for _dir in torrent.waiting_on_folder_rename if _dir]
component.get('TorrentManager').save_resume_data((self.torrent_id,))
d = DeferredList(wait_on_folder.values())
d = DeferredList(list(wait_on_folder.values()))
d.addBoth(on_folder_rename_complete, self, folder, new_folder)
return d

View file

@ -10,7 +10,7 @@
"""TorrentManager handles Torrent objects"""
from __future__ import unicode_literals
import cPickle
import cPickle as pickle
import datetime
import logging
import operator
@ -262,7 +262,7 @@ class TorrentManager(component.Component):
list: A list of torrent_ids.
"""
torrent_ids = self.torrents.keys()
torrent_ids = list(self.torrents.keys())
if component.get('RPCServer').get_session_auth_level() == AUTH_LEVEL_ADMIN:
return torrent_ids
@ -493,8 +493,8 @@ class TorrentManager(component.Component):
log.info('Loading torrent state: %s', filepath)
try:
with open(filepath, 'rb') as _file:
state = cPickle.load(_file)
except (IOError, EOFError, cPickle.UnpicklingError) as ex:
state = pickle.load(_file)
except (IOError, EOFError, pickle.UnpicklingError) as ex:
log.warning('Unable to load %s: %s', filepath, ex)
state = None
else:
@ -640,10 +640,10 @@ class TorrentManager(component.Component):
try:
log.debug('Creating the temporary file: %s', filepath_tmp)
with open(filepath_tmp, 'wb', 0) as _file:
cPickle.dump(state, _file)
pickle.dump(state, _file)
_file.flush()
os.fsync(_file.fileno())
except (OSError, cPickle.PicklingError) as ex:
except (OSError, pickle.PicklingError) as ex:
log.error('Unable to save %s: %s', filename, ex)
return
@ -680,7 +680,7 @@ class TorrentManager(component.Component):
"""
if torrent_ids is None:
torrent_ids = (t[0] for t in self.torrents.iteritems() if t[1].handle.need_save_resume_data())
torrent_ids = (tid for tid, t in self.torrents.items() if t.handle.need_save_resume_data())
def on_torrent_resume_save(dummy_result, torrent_id):
"""Recieved torrent resume_data alert so remove from waiting list"""
@ -852,8 +852,8 @@ class TorrentManager(component.Component):
def cleanup_torrents_prev_status(self):
"""Run cleanup_prev_status for each registered torrent"""
for torrent in self.torrents.iteritems():
torrent[1].cleanup_prev_status()
for torrent in self.torrents.values():
torrent.cleanup_prev_status()
def on_set_max_connections_per_torrent(self, key, value):
"""Sets the per-torrent connection limit"""
@ -1270,7 +1270,7 @@ class TorrentManager(component.Component):
if self.torrents:
for torrent_id in torrent_ids:
if torrent_id in self.torrents:
status_keys = self.torrents[torrent_id].status_funcs.keys()
status_keys = list(self.torrents[torrent_id].status_funcs.keys())
leftover_keys = list(set(keys) - set(status_keys))
torrent_keys = list(set(keys) - set(leftover_keys))
return torrent_keys, leftover_keys

View file

@ -27,9 +27,9 @@ log = logging.getLogger(__name__)
ignore = ['core', 'CVS', 'Thumbs.db', 'desktop.ini']
noncharacter_translate = {}
for i in xrange(0xD800, 0xE000):
for i in range(0xD800, 0xE000):
noncharacter_translate[i] = ord('-')
for i in xrange(0xFDD0, 0xFDF0):
for i in range(0xFDD0, 0xFDF0):
noncharacter_translate[i] = ord('-')
for i in (0xFFFE, 0xFFFF):
noncharacter_translate[i] = ord('-')

View file

@ -88,7 +88,7 @@ class PluginManagerBase(object):
def get_enabled_plugins(self):
"""Returns a list of enabled plugins"""
return self.plugins.keys()
return list(self.plugins.keys())
def scan_for_plugins(self):
"""Scans for available plugins"""
@ -245,14 +245,14 @@ class PluginManagerBase(object):
for line in self.pkg_env[name][0].get_metadata('PKG-INFO').splitlines():
if not line:
continue
if line[0] in ' \t' and (len(line.split(':', 1)) == 1 or line.split(':', 1)[0] not in info.keys()):
if line[0] in ' \t' and (len(line.split(':', 1)) == 1 or line.split(':', 1)[0] not in list(info.keys())):
# This is a continuation
cont_lines.append(line.strip())
else:
if cont_lines:
info[last_header] = '\n'.join(cont_lines).strip()
cont_lines = []
if line.split(':', 1)[0] in info.keys():
if line.split(':', 1)[0] in list(info.keys()):
last_header = line.split(':', 1)[0]
info[last_header] = line.split(':', 1)[1].strip()
return info

View file

@ -101,7 +101,7 @@ class Core(CorePluginBase):
def enable_looping(self):
# Enable all looping calls for enabled watchdirs here
for watchdir_id, watchdir in self.watchdirs.iteritems():
for watchdir_id, watchdir in self.watchdirs.items():
if watchdir['enabled']:
self.enable_watchdir(watchdir_id)
@ -110,7 +110,7 @@ class Core(CorePluginBase):
component.get('EventManager').deregister_event_handler(
'PreTorrentRemovedEvent', self.__on_pre_torrent_removed
)
for loopingcall in self.update_timers.itervalues():
for loopingcall in self.update_timers.values():
loopingcall.stop()
self.config.save()
@ -130,12 +130,12 @@ class Core(CorePluginBase):
check_input(
os.path.isdir(options['abspath']), _('Path does not exist.')
)
for w_id, w in self.watchdirs.iteritems():
for w_id, w in self.watchdirs.items():
if options['abspath'] == w['abspath'] and watchdir_id != w_id:
raise Exception('Path is already being watched.')
for key in options:
if key not in OPTIONS_AVAILABLE:
if key not in [key2 + '_toggle' for key2 in OPTIONS_AVAILABLE.iterkeys()]:
if key not in [key2 + '_toggle' for key2 in OPTIONS_AVAILABLE]:
raise Exception('autoadd: Invalid options key:%s' % key)
# disable the watch loop if it was active
if watchdir_id in self.update_timers:
@ -225,7 +225,7 @@ class Core(CorePluginBase):
watchdir['stop_ratio_toggle'] = watchdir['stop_at_ratio_toggle']
# We default to True when reading _toggle values, so a config
# without them is valid, and applies all its settings.
for option, value in watchdir.iteritems():
for option, value in watchdir.items():
if OPTIONS_AVAILABLE.get(option):
if watchdir.get(option + '_toggle', True) or option in ['owner', 'seed_mode']:
opts[option] = value
@ -383,12 +383,12 @@ class Core(CorePluginBase):
return self.watchdirs
watchdirs = {}
for watchdir_id, watchdir in self.watchdirs.iteritems():
for watchdir_id, watchdir in self.watchdirs.items():
if watchdir.get('owner', 'localclient') == session_user:
watchdirs[watchdir_id] = watchdir
log.debug('Current logged in user %s is not an ADMIN, send only '
'his watchdirs: %s', session_user, watchdirs.keys())
'his watchdirs: %s', session_user, list(watchdirs.keys()))
return watchdirs
def _make_unicode(self, options):
@ -411,7 +411,7 @@ class Core(CorePluginBase):
os.access(abswatchdir, os.R_OK | os.W_OK),
'You must have read and write access to watch folder.'
)
if abswatchdir in [wd['abspath'] for wd in self.watchdirs.itervalues()]:
if abswatchdir in [wd['abspath'] for wd in self.watchdirs.values()]:
raise Exception('Path is already being watched.')
options.setdefault('enabled', False)
options['abspath'] = abswatchdir
@ -436,7 +436,7 @@ class Core(CorePluginBase):
component.get('EventManager').emit(AutoaddOptionsChangedEvent())
def __migrate_config_1_to_2(self, config):
for watchdir_id in config['watchdirs'].iterkeys():
for watchdir_id in config['watchdirs']:
config['watchdirs'][watchdir_id]['owner'] = 'localclient'
return config
@ -449,7 +449,7 @@ class Core(CorePluginBase):
torrent_id)
return
torrent_fname = torrent.filename
for watchdir in self.watchdirs.itervalues():
for watchdir in self.watchdirs.values():
if not watchdir.get('copy_torrent_toggle', False):
# This watchlist does copy torrents
continue

View file

@ -403,7 +403,7 @@ class GtkUI(GtkPluginBase):
def create_model(self):
store = gtk.ListStore(str, bool, str, str)
for watchdir_id, watchdir in self.watchdirs.iteritems():
for watchdir_id, watchdir in self.watchdirs.items():
store.append([
watchdir_id, watchdir['enabled'],
watchdir.get('owner', 'localclient'), watchdir['path']
@ -476,7 +476,7 @@ class GtkUI(GtkPluginBase):
def on_apply_prefs(self):
log.debug('applying prefs for AutoAdd')
for watchdir_id, watchdir in self.watchdirs.iteritems():
for watchdir_id, watchdir in self.watchdirs.items():
client.autoadd.set_options(watchdir_id, watchdir)
def on_show_prefs(self):
@ -490,7 +490,7 @@ class GtkUI(GtkPluginBase):
log.trace('Got whatchdirs from core: %s', watchdirs)
self.watchdirs = watchdirs or {}
self.store.clear()
for watchdir_id, watchdir in self.watchdirs.iteritems():
for watchdir_id, watchdir in self.watchdirs.items():
self.store.append([
watchdir_id, watchdir['enabled'],
watchdir.get('owner', 'localclient'), watchdir['path']

View file

@ -134,7 +134,7 @@ class Core(CorePluginBase):
def disable(self):
self.config.save()
event_manager = component.get('EventManager')
for event, handler in self.registered_events.iteritems():
for event, handler in self.registered_events.items():
event_manager.deregister_event_handler(event, handler)
log.debug('Execute core plugin disabled!')

View file

@ -40,14 +40,18 @@ if windows_check():
'C:\\Program Files (x86)\\7-Zip\\7z.exe',
]
import _winreg
try:
hkey = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, 'Software\\7-Zip')
import winreg
except ImportError:
import _winreg as winreg # For Python 2.
try:
hkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 'Software\\7-Zip')
except WindowsError:
pass
else:
win_7z_path = os.path.join(_winreg.QueryValueEx(hkey, 'Path')[0], '7z.exe')
_winreg.CloseKey(hkey)
win_7z_path = os.path.join(winreg.QueryValueEx(hkey, 'Path')[0], '7z.exe')
winreg.CloseKey(hkey)
win_7z_exes.insert(1, win_7z_path)
switch_7z = 'x -y'

View file

@ -109,7 +109,7 @@ class Core(CorePluginBase):
def init_filter_dict(self):
filter_dict = dict([(label, 0) for label in self.labels.keys()])
filter_dict['All'] = len(self.torrents.keys())
filter_dict['All'] = len(self.torrents)
return filter_dict
# Plugin hooks #
@ -119,7 +119,7 @@ class Core(CorePluginBase):
log.debug('post_torrent_add')
torrent = self.torrents[torrent_id]
for label_id, options in self.labels.iteritems():
for label_id, options in self.labels.items():
if options['auto_add']:
if self._has_auto_match(torrent, options):
self.set_torrent(torrent_id, label_id)
@ -133,7 +133,7 @@ class Core(CorePluginBase):
# Utils #
def clean_config(self):
"""remove invalid data from config-file"""
for torrent_id, label_id in list(self.torrent_labels.iteritems()):
for torrent_id, label_id in list(self.torrent_labels.items()):
if (label_id not in self.labels) or (torrent_id not in self.torrents):
log.debug('label: rm %s:%s', torrent_id, label_id)
del self.torrent_labels[torrent_id]
@ -143,7 +143,7 @@ class Core(CorePluginBase):
*add any new keys in OPTIONS_DEFAULTS
*set all None values to default <-fix development config
"""
log.debug(self.labels.keys())
log.debug(list(self.labels.keys()))
for key in self.labels.keys():
options = dict(OPTIONS_DEFAULTS)
options.update(self.labels[key])
@ -267,14 +267,14 @@ class Core(CorePluginBase):
self.labels[label_id].update(options_dict)
# apply
for torrent_id, label in self.torrent_labels.iteritems():
for torrent_id, label in self.torrent_labels.items():
if label_id == label and torrent_id in self.torrents:
self._set_torrent_options(torrent_id, label_id)
# auto add
options = self.labels[label_id]
if options['auto_add']:
for torrent_id, torrent in self.torrents.iteritems():
for torrent_id, torrent in self.torrents.items():
if self._has_auto_match(torrent, options):
self.set_torrent(torrent_id, label_id)

View file

@ -174,7 +174,7 @@ class OptionsDialog(object):
self.dialog.run()
def load_options(self, options):
log.debug(options.keys())
log.debug(list(options.keys()))
for spin_id in self.spin_ids + self.spin_int_ids:
self.glade.get_widget(spin_id).set_value(options[spin_id])

View file

@ -19,15 +19,10 @@ import logging
from twisted.internet import defer
from deluge import component
from deluge.event import known_events
log = logging.getLogger(__name__)
try:
from deluge.event import known_events
except ImportError:
# Old deluge version
known_events = {}
def get_resource(filename):
import os
@ -49,8 +44,8 @@ class CustomNotifications(object):
pass
def disable(self):
for kind in self.custom_notifications.iterkeys():
for eventtype in self.custom_notifications[kind].copy().iterkeys():
for kind in self.custom_notifications:
for eventtype in list(self.custom_notifications[kind]):
wrapper, handler = self.custom_notifications[kind][eventtype]
self._deregister_custom_provider(kind, eventtype)

View file

@ -67,10 +67,10 @@ DEFAULT_PREFS = {
},
}
RECIPIENT_FIELD, RECIPIENT_EDIT = range(2)
RECIPIENT_FIELD, RECIPIENT_EDIT = list(range(2))
(SUB_EVENT, SUB_EVENT_DOC, SUB_NOT_EMAIL, SUB_NOT_POPUP, SUB_NOT_BLINK,
SUB_NOT_SOUND) = range(6)
SND_EVENT, SND_EVENT_DOC, SND_NAME, SND_PATH = range(4)
SUB_NOT_SOUND) = list(range(6))
SND_EVENT, SND_EVENT_DOC, SND_NAME, SND_PATH = list(range(4))
class GtkUiNotifications(CustomNotifications):

View file

@ -32,7 +32,7 @@ DEFAULT_PREFS = {
'low_active': -1,
'low_active_down': -1,
'low_active_up': -1,
'button_state': [[0] * 7 for dummy in xrange(24)]
'button_state': [[0] * 7 for dummy in range(24)]
}
STATES = {

View file

@ -43,7 +43,7 @@ class SchedulerSelectWidget(gtk.DrawingArea):
self.colors = [[115 / 255, 210 / 255, 22 / 255],
[237 / 255, 212 / 255, 0 / 255],
[204 / 255, 0 / 255, 0 / 255]]
self.button_state = [[0] * 7 for dummy in xrange(24)]
self.button_state = [[0] * 7 for dummy in range(24)]
self.start_point = [0, 0]
self.hover_point = [-1, -1]
@ -67,8 +67,8 @@ class SchedulerSelectWidget(gtk.DrawingArea):
width = self.window.get_size()[0]
height = self.window.get_size()[1]
for y in xrange(7):
for x in xrange(24):
for y in range(7):
for x in range(24):
context.set_source_rgba(self.colors[self.button_state[x][y]][0],
self.colors[self.button_state[x][y]][1],
self.colors[self.button_state[x][y]][2], 0.7)
@ -130,8 +130,8 @@ class SchedulerSelectWidget(gtk.DrawingArea):
if self.mouse_press:
points = [[self.hover_point[0], self.start_point[0]], [self.hover_point[1], self.start_point[1]]]
for x in xrange(min(points[0]), max(points[0]) + 1):
for y in xrange(min(points[1]), max(points[1]) + 1):
for x in range(min(points[0]), max(points[0]) + 1):
for y in range(min(points[1]), max(points[1]) + 1):
self.button_state[x][y] = self.button_state[self.start_point[0]][self.start_point[1]]
self.queue_draw()

View file

@ -136,7 +136,7 @@ class Core(CorePluginBase):
# extract the ones we are interested in
# adding them to the 1s array
for stat, stat_list in self.stats[1].iteritems():
for stat, stat_list in self.stats[1].items():
if stat in stats:
stat_list.insert(0, int(stats[stat]))
else:
@ -150,7 +150,7 @@ class Core(CorePluginBase):
self.last_update[interval] = update_time
self.count[interval] = 0
current_stats = self.stats[interval]
for stat, stat_list in self.stats[base].iteritems():
for stat, stat_list in self.stats[base].items():
try:
avg = mean(stat_list[0:multiplier])
except ValueError:

View file

@ -135,7 +135,7 @@ class Graph(object):
# this doesnt allow for dst and timezones...
seconds_to_step = math.ceil(start / x_step) * x_step - start
for i in xrange(0, duration // x_step + 1):
for i in range(0, duration // x_step + 1):
text = time.strftime('%H:%M', time.localtime(start + seconds_to_step + i * x_step))
# + 0.5 to allign x to nearest pixel
x = int(ratio * (seconds_to_step + i * x_step) + left) + 0.5
@ -220,7 +220,7 @@ class Graph(object):
else:
interval = interval * 2
intervals = [i * interval * scale for i in xrange(1 + int(math.ceil(x / interval)))]
intervals = [i * interval * scale for i in range(1 + int(math.ceil(x / interval)))]
return intervals
def draw_left_axis(self, bounds, y_ticks, y_tick_text):
@ -244,7 +244,7 @@ class Graph(object):
self.draw_y_text(y_tick_text[i], left, y)
self.draw_line(gray, left, top, left, bottom)
for stat, info in stats.iteritems():
for stat, info in stats.items():
if len(info['values']) > 0:
self.draw_value_poly(info['values'], info['color'], max_value, bounds)
self.draw_value_poly(info['values'], info['fill_color'], max_value, bounds, info['fill'])

View file

@ -129,7 +129,7 @@ class GraphsTab(Tab):
return False
def update(self):
d1 = client.stats.get_stats(self.graph.stat_info.keys(), self.selected_interval)
d1 = client.stats.get_stats(list(self.graph.stat_info.keys()), self.selected_interval)
d1.addCallback(self.graph.set_stats)
def _update_complete(result):

View file

@ -18,7 +18,7 @@ from deluge.ui.client import client
def print_totals(totals):
for name, value in totals.iteritems():
for name, value in totals.items():
print(name, fsize(value))
print('overhead:')

View file

@ -60,6 +60,7 @@ same rencode version throughout your project.
import struct
import sys
from future_builtins import zip
from threading import Lock
__version__ = ('Python', 1, 0, 4)

View file

@ -8,7 +8,6 @@
from __future__ import unicode_literals
import base64
import sys
from hashlib import sha1 as sha
import pytest
@ -23,6 +22,7 @@ from twisted.web.static import File
import deluge.common
import deluge.component as component
import deluge.core.torrent
from deluge.common import PY2
from deluge.core.core import Core
from deluge.core.rpcserver import RPCServer
from deluge.error import AddTorrentError, InvalidTorrentError
@ -270,10 +270,7 @@ class CoreTestCase(BaseTestCase):
def test_get_free_space(self):
space = self.core.get_free_space('.')
# get_free_space returns long on Python 2 (32-bit).
if sys.version_info >= (3, 0):
self.assertTrue(isinstance(space, int))
else:
self.assertTrue(isinstance(space, (int, long)))
self.assertTrue(isinstance(space, int if not PY2 else (int, long)))
self.assertTrue(space >= 0)
self.assertEquals(self.core.get_free_space('/someinvalidpath'), -1)

View file

@ -187,7 +187,7 @@ class RPCRaiseDelugeErrorJSONTestCase(JSONBase):
self.assertTrue('testclass.test' in methods)
request = MagicMock()
request.getCookie = MagicMock(return_value=auth.config['sessions'].keys()[0])
request.getCookie = MagicMock(return_value=list(auth.config['sessions'].keys())[0])
json_data = {'method': 'testclass.test', 'id': 0, 'params': []}
request.json = json_lib.dumps(json_data)
request_id, result, error = json._handle_request(request)

View file

@ -35,7 +35,7 @@ class Core(object):
def get_torrent_status(self, torrent_id, keys, diff=False):
if not keys:
keys = self.torrents[torrent_id].keys()
keys = list(self.torrents[torrent_id].keys())
if not diff:
ret = {}
@ -57,9 +57,9 @@ class Core(object):
def get_torrents_status(self, filter_dict, keys, diff=False):
if not filter_dict:
filter_dict['id'] = self.torrents.keys()
filter_dict['id'] = list(self.torrents.keys())
if not keys:
keys = self.torrents['a'].keys()
keys = list(self.torrents['a'].keys())
if not diff:
if 'id' in filter_dict:
torrents = filter_dict['id']

View file

@ -152,7 +152,7 @@ class GtkUIBaseTestCase(UIBaseTestCase):
"""Implement all GtkUI tests here"""
def test_start_gtkui(self):
self.patch(sys, 'argv', self.var['sys_arg_cmd'])
self.patch(sys, 'argv', utf8_encode_structure(self.var['sys_arg_cmd']))
from deluge.ui.gtkui import gtkui
with mock.patch.object(gtkui.GtkUI, 'start', autospec=True):
@ -168,7 +168,7 @@ class GtkUIDelugeScriptEntryTestCase(BaseTestCase, GtkUIBaseTestCase):
self.var['cmd_name'] = 'deluge gtk'
self.var['start_cmd'] = ui_entry.start_ui
self.var['sys_arg_cmd'] = utf8_encode_structure(['./deluge', 'gtk'])
self.var['sys_arg_cmd'] = ['./deluge', 'gtk']
def set_up(self):
return GtkUIBaseTestCase.set_up(self)

View file

@ -48,6 +48,7 @@ from __future__ import division, unicode_literals
import logging
import struct
from future_builtins import zip
import PIL.BmpImagePlugin
import PIL.Image
@ -77,9 +78,9 @@ class Win32IcoFile(object):
self.nb_items = header[2]
dir_fields = ('width', 'height', 'nb_color', 'reserved', 'planes', 'bpp', 'size', 'offset')
for i in xrange(self.nb_items):
for i in range(self.nb_items):
directory = list(struct.unpack('<4B2H2I', buf.read(16)))
for j in xrange(3):
for j in range(3):
if not directory[j]:
directory[j] = 256
icon_header = dict(zip(dir_fields, directory))

View file

@ -397,7 +397,7 @@ class DaemonSSLProxy(DaemonProxy):
# We need to tell the daemon what events we're interested in receiving
if self.__factory.event_handlers:
self.call('daemon.set_event_interest',
self.__factory.event_handlers.keys())
list(self.__factory.event_handlers.keys()))
self.call('core.get_auth_levels_mappings').addCallback(
self.__on_auth_levels_mappings

View file

@ -207,7 +207,7 @@ class TorrentInfo(object):
item.update(paths[path])
item['download'] = True
file_tree = FileTree2(paths.keys())
file_tree = FileTree2(list(paths.keys()))
file_tree.walk(walk)
else:
def walk(path, item):

View file

@ -12,8 +12,6 @@ from __future__ import unicode_literals
import base64
import os
from urllib import url2pathname
from urlparse import urlparse
from twisted.internet import defer
@ -23,6 +21,14 @@ from deluge.ui.client import client
from . import BaseCommand
try:
from urllib.parse import urlparse
from urllib.request import url2pathname
except ImportError:
# PY2 fallback
from urlparse import urlparse # pylint: disable=ungrouped-imports
from urllib import url2pathname # pylint: disable=ungrouped-imports
class Command(BaseCommand):
"""Add torrents"""

View file

@ -123,7 +123,7 @@ class Command(BaseCommand):
self.console.write('{!error!}%s' % ex)
return
if key not in config.keys():
if key not in list(config.keys()):
self.console.write('{!error!}Invalid key: %s' % key)
return

View file

@ -147,7 +147,7 @@ class Command(BaseCommand):
self.console.write('{!error!}Unknown sort key: ' + sort_key + ', will sort on name')
sort_key = 'name'
sort_reverse = False
for key, value in sorted(status.items(), key=lambda x: x[1].get(sort_key), reverse=sort_reverse):
for key, value in sorted(list(status.items()), key=lambda x: x[1].get(sort_key), reverse=sort_reverse):
self.show_info(key, status[key], options.verbose, options.detailed)
def on_torrents_status_fail(reason):

View file

@ -12,6 +12,7 @@ from __future__ import unicode_literals
import base64
import logging
import os
from future_builtins import zip
import deluge.common
import deluge.component as component
@ -513,9 +514,9 @@ class AddTorrents(BaseMode):
elif chr(c) == 'M':
if self.last_mark != -1:
if self.last_mark > self.cursel:
m = range(self.cursel, self.last_mark)
m = list(range(self.cursel, self.last_mark))
else:
m = range(self.last_mark, self.cursel + 1)
m = list(range(self.last_mark, self.cursel + 1))
for i in m:
s = self.raw_rows[i][0]

View file

@ -68,7 +68,7 @@ arrow to edit the other value, and escape to get back to the check box.
class ZONE(object):
length = 3
CATEGORIES, PREFRENCES, ACTIONS = range(length)
CATEGORIES, PREFRENCES, ACTIONS = list(range(length))
class PreferenceSidebar(Sidebar):

View file

@ -79,7 +79,7 @@ class QueueMode(object):
self.torrentview.cursel = 1 + sorted(self.torrentview.marked).index(self.torrentview.cursel)
else:
self.torrentview.cursel = 1
self.torrentview.marked = range(1, selected_num + 1)
self.torrentview.marked = list(range(1, selected_num + 1))
elif qact == ACTION.QUEUE_UP:
self.torrentview.cursel = max(1, self.torrentview.cursel - 1)
self.torrentview.marked = [marked - 1 for marked in self.torrentview.marked]
@ -94,7 +94,7 @@ class QueueMode(object):
sorted(self.torrentview.marked).index(self.torrentview.cursel))
else:
self.torrentview.cursel = queue_length
self.torrentview.marked = range(queue_length - selected_num + 1, queue_length + 1)
self.torrentview.marked = list(range(queue_length - selected_num + 1, queue_length + 1))
def do_queue(self, qact, *args, **kwargs):
if qact == ACTION.QUEUE_TOP:

View file

@ -103,7 +103,7 @@ def action_torrent_info(mode=None, torrent_ids=None, **kwargs):
def _do_set_torrent_options(torrent_ids, result):
options = {}
for opt, val in result.iteritems():
for opt, val in result.items():
if val['value'] not in ['multiple', None]:
options[opt] = val['value']
client.core.set_torrent_options(torrent_ids, options)

View file

@ -235,7 +235,7 @@ class TorrentView(InputKeyHandler):
# Get first element so we can check if it has given field
# and if it's a string
first_element = state[state.keys()[0]]
first_element = state[list(state.keys())[0]]
if field in first_element:
def sort_key(s):
try:
@ -449,9 +449,9 @@ class TorrentView(InputKeyHandler):
elif c == ord('M'):
if self.last_mark >= 0:
if self.cursel > self.last_mark:
mrange = range(self.last_mark, self.cursel + 1)
mrange = list(range(self.last_mark, self.cursel + 1))
else:
mrange = range(self.cursel, self.last_mark)
mrange = list(range(self.cursel, self.last_mark))
self.add_marked(mrange, self.cursel)
affected_lines = mrange
else:

View file

@ -260,7 +260,7 @@ class SelectablePopup(BaseInputPane, Popup):
@overrides(Popup, BaseInputPane)
def handle_read(self, c):
if c in [curses.KEY_ENTER, util.KEY_ENTER2]:
for k, v in self.get_values().iteritems():
for k, v in self.get_values().items():
if v['active']:
if self.selection_cb(k, **dict(self.cb_args, data=self.cb_arg)):
self.close(None)

View file

@ -299,7 +299,7 @@ class AddTorrentDialog(component.Component):
def add_files(self, parent_iter, split_files):
ret = 0
for key, value in split_files.iteritems():
for key, value in split_files.items():
if key.endswith(os.path.sep):
chunk_iter = self.files_treestore.append(
parent_iter, [True, key, 0, -1, False, gtk.STOCK_DIRECTORY])

View file

@ -10,7 +10,7 @@
from __future__ import unicode_literals
import contextlib
import cPickle
import cPickle as pickle
import logging
import os
import shutil
@ -143,7 +143,7 @@ def reparent_iter(treestore, itr, parent, move_siblings=False):
def move_children(i, dest):
while i:
n_cols = treestore.append(dest, treestore.get(i, *xrange(treestore.get_n_columns())))
n_cols = treestore.append(dest, treestore.get(i, *range(treestore.get_n_columns())))
to_remove = i
if treestore.iter_children(i):
move_children(treestore.iter_children(i), n_cols)
@ -188,29 +188,32 @@ def associate_magnet_links(overwrite=False):
"""
if windows_check():
import _winreg
try:
import winreg
except ImportError:
import _winreg as winreg # For Python 2.
try:
hkey = _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT, 'Magnet')
hkey = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, 'Magnet')
except WindowsError:
overwrite = True
else:
_winreg.CloseKey(hkey)
winreg.CloseKey(hkey)
if overwrite:
deluge_exe = os.path.join(os.path.dirname(sys.executable), 'deluge.exe')
try:
magnet_key = _winreg.CreateKey(_winreg.HKEY_CLASSES_ROOT, 'Magnet')
magnet_key = winreg.CreateKey(winreg.HKEY_CLASSES_ROOT, 'Magnet')
except WindowsError:
# Could not create for all users, falling back to current user
magnet_key = _winreg.CreateKey(_winreg.HKEY_CURRENT_USER, 'Software\\Classes\\Magnet')
magnet_key = winreg.CreateKey(winreg.HKEY_CURRENT_USER, 'Software\\Classes\\Magnet')
_winreg.SetValue(magnet_key, '', _winreg.REG_SZ, 'URL:Magnet Protocol')
_winreg.SetValueEx(magnet_key, 'URL Protocol', 0, _winreg.REG_SZ, '')
_winreg.SetValueEx(magnet_key, 'BrowserFlags', 0, _winreg.REG_DWORD, 0x8)
_winreg.SetValue(magnet_key, 'DefaultIcon', _winreg.REG_SZ, '{},0'.format(deluge_exe))
_winreg.SetValue(magnet_key, r'shell\open\command', _winreg.REG_SZ, '"{}" "%1"'.format(deluge_exe))
_winreg.CloseKey(magnet_key)
winreg.SetValue(magnet_key, '', winreg.REG_SZ, 'URL:Magnet Protocol')
winreg.SetValueEx(magnet_key, 'URL Protocol', 0, winreg.REG_SZ, '')
winreg.SetValueEx(magnet_key, 'BrowserFlags', 0, winreg.REG_DWORD, 0x8)
winreg.SetValue(magnet_key, 'DefaultIcon', winreg.REG_SZ, '{},0'.format(deluge_exe))
winreg.SetValue(magnet_key, r'shell\open\command', winreg.REG_SZ, '"{}" "%1"'.format(deluge_exe))
winreg.CloseKey(magnet_key)
# Don't try associate magnet on OSX see: #2420
elif not osx_check():
@ -259,11 +262,11 @@ def save_pickled_state_file(filename, state):
try:
with open(filepath_tmp, 'wb') as _file:
# Pickle the state object
cPickle.dump(state, _file)
pickle.dump(state, _file)
_file.flush()
os.fsync(_file.fileno())
shutil.move(filepath_tmp, filepath)
except (IOError, EOFError, cPickle.PicklingError) as ex:
except (IOError, EOFError, pickle.PicklingError) as ex:
log.error('Unable to save %s: %s', filename, ex)
if os.path.isfile(filepath_bak):
log.info('Restoring backup of %s from: %s', filename, filepath_bak)
@ -288,8 +291,8 @@ def load_pickled_state_file(filename):
log.info('Opening %s for load: %s', filename, _filepath)
try:
with open(_filepath, 'rb') as _file:
state = cPickle.load(_file)
except (IOError, cPickle.UnpicklingError) as ex:
state = pickle.load(_file)
except (IOError, pickle.UnpicklingError) as ex:
log.warning('Unable to load %s: %s', _filepath, ex)
else:
log.info('Successfully loaded %s: %s', filename, _filepath)

View file

@ -9,7 +9,7 @@
from __future__ import division, unicode_literals
import cPickle
import cPickle as pickle
import logging
import os.path
@ -344,7 +344,7 @@ class FilesTab(Tab):
def add_files(self, parent_iter, split_files):
chunk_size_total = 0
for key, value in split_files.iteritems():
for key, value in split_files.items():
if key.endswith('/'):
chunk_iter = self.treestore.append(parent_iter,
[key, 0, '', 0, 0, -1, gtk.STOCK_DIRECTORY])
@ -623,7 +623,7 @@ class FilesTab(Tab):
p_itr = self.get_iter_at_path('/'.join(parent_path) + '/')
old_name_itr = self.get_iter_at_path(old_name)
self.treestore.append(p_itr,
self.treestore.get(old_name_itr, *xrange(self.treestore.get_n_columns())))
self.treestore.get(old_name_itr, *range(self.treestore.get_n_columns())))
self.treestore.remove(old_name_itr)
# Remove old parent path
@ -637,7 +637,7 @@ class FilesTab(Tab):
parent_iter, [f + '/', 0, '', 0, 0, -1, gtk.STOCK_DIRECTORY])
child = self.get_iter_at_path(old_name)
self.treestore.append(parent_iter,
self.treestore.get(child, *xrange(self.treestore.get_n_columns())))
self.treestore.get(child, *range(self.treestore.get_n_columns())))
self.treestore.remove(child)
else:
@ -750,12 +750,12 @@ class FilesTab(Tab):
def _on_drag_data_get_data(self, treeview, context, selection, target_id, etime):
paths = self.listview.get_selection().get_selected_rows()[1]
selection.set_text(cPickle.dumps(paths))
selection.set_text(pickle.dumps(paths))
def _on_drag_data_received_data(self, treeview, context, x, y, selection, info, etime):
try:
selected = cPickle.loads(selection.data)
except cPickle.UnpicklingError:
selected = pickle.loads(selection.data)
except pickle.UnpicklingError:
log.debug('Invalid selection data: %s', selection.data)
return
log.debug('selection.data: %s', selected)

View file

@ -161,7 +161,7 @@ class FilterTreeView(component.Component):
# update rows
visible_filters = []
for cat, filters in filter_items.iteritems():
for cat, filters in filter_items.items():
for value, count in filters:
self.update_row(cat, value, count)
visible_filters.append((cat, value))

View file

@ -15,8 +15,6 @@ import os
import sys
from glob import glob
from tempfile import mkstemp
from urllib import url2pathname
from urlparse import urlparse
import twisted.internet.error
from twisted.internet import reactor
@ -32,6 +30,14 @@ try:
except ImportError:
import deluge.rencode as rencode # pylint: disable=ungrouped-imports
try:
from urllib.parse import urlparse
from urllib.request import url2pathname
except ImportError:
# PY2 fallback
from urlparse import urlparse # pylint: disable=ungrouped-imports
from urllib import url2pathname # pylint: disable=ungrouped-imports
log = logging.getLogger(__name__)

View file

@ -118,7 +118,7 @@ class ListView(object):
def set_col_attributes(self, renderer, add=True, **kw):
if add is True:
for attr, value in kw.iteritems():
for attr, value in kw.items():
self.add_attribute(renderer, attr, value)
else:
self.set_attributes(renderer, **kw)

View file

@ -39,7 +39,7 @@ class _GtkBuilderSignalsHolder(object):
def connect_signals(self, mapping_or_class):
if isinstance(mapping_or_class, dict):
for name, handler in mapping_or_class.iteritems():
for name, handler in mapping_or_class.items():
if hasattr(self, name):
raise RuntimeError(
'A handler for signal %r has already been registered: %s' %

View file

@ -411,7 +411,7 @@ class MenuBar(component.Component):
'menuitem_max_connections': 'max_connections',
'menuitem_upload_slots': 'max_upload_slots'
}
if widget.get_name() in funcs.keys():
if widget.get_name() in list(funcs.keys()):
torrent_ids = component.get('TorrentView').get_selected_torrents()
client.core.set_torrent_options(torrent_ids, {funcs[widget.get_name()]: -1})
@ -494,7 +494,7 @@ class MenuBar(component.Component):
known_accounts_to_log = []
for account in known_accounts:
account_to_log = {}
for key, value in account.copy().iteritems():
for key, value in account.copy().items():
if key == 'password':
value = '*' * len(value)
account_to_log[key] = value
@ -537,7 +537,7 @@ class MenuBar(component.Component):
return
torrent_owner = component.get('TorrentView').get_torrent_status(selected[0])['owner']
for username, item in self.change_owner_submenu_items.iteritems():
for username, item in self.change_owner_submenu_items.items():
item.set_active(username == torrent_owner)
def _on_change_owner_toggled(self, widget, username):

View file

@ -116,7 +116,7 @@ class OptionsTab(Tab):
# We only want to update values that have been applied in the core. This
# is so we don't overwrite the user changes that haven't been applied yet.
if self.prev_status is None:
self.prev_status = {}.fromkeys(status.keys(), None)
self.prev_status = {}.fromkeys(list(status.keys()), None)
if status != self.prev_status:
if status['max_download_speed'] != self.prev_status['max_download_speed']:

View file

@ -60,7 +60,7 @@ class PathChoosersHandler(component.Component):
self.config_properties.update(config)
for chooser in self.path_choosers:
chooser.set_config(config)
keys = self.config_keys_to_funcs_mapping.keys()
keys = list(self.config_keys_to_funcs_mapping.keys())
keys += self.paths_list_keys
client.core.get_config_values(keys).addCallback(_on_config_values)
@ -109,7 +109,7 @@ class PathChoosersHandler(component.Component):
chooser.set_values(values)
def get_config_keys(self):
keys = self.config_keys_to_funcs_mapping.keys()
keys = list(self.config_keys_to_funcs_mapping.keys())
keys += self.paths_list_keys
return keys

View file

@ -36,8 +36,8 @@ except ImportError:
log = logging.getLogger(__name__)
ACCOUNTS_USERNAME, ACCOUNTS_LEVEL, ACCOUNTS_PASSWORD = range(3)
COLOR_MISSING, COLOR_WAITING, COLOR_DOWNLOADING, COLOR_COMPLETED = range(4)
ACCOUNTS_USERNAME, ACCOUNTS_LEVEL, ACCOUNTS_PASSWORD = list(range(3))
COLOR_MISSING, COLOR_WAITING, COLOR_DOWNLOADING, COLOR_COMPLETED = list(range(4))
COLOR_STATES = {
'missing': COLOR_MISSING,
@ -1020,7 +1020,7 @@ class Preferences(component.Component):
known_accounts_to_log = []
for account in known_accounts:
account_to_log = {}
for key, value in account.copy().iteritems():
for key, value in account.copy().items():
if key == 'password':
value = '*' * len(value)
account_to_log[key] = value

View file

@ -287,7 +287,7 @@ class StatusBar(component.Component):
This is called when we receive a ConfigValueChangedEvent from
the core.
"""
if key in self.config_value_changed_dict.keys():
if key in list(self.config_value_changed_dict.keys()):
self.config_value_changed_dict[key](value)
def _on_max_connections_global(self, max_connections):

View file

@ -179,7 +179,7 @@ class SystemTray(component.Component):
def config_value_changed(self, key, value):
"""This is called when we received a config_value_changed signal from
the core."""
if key in self.config_value_changed_dict.keys():
if key in list(self.config_value_changed_dict.keys()):
self.config_value_changed_dict[key](value)
def _on_max_download_speed(self, max_download_speed):

View file

@ -129,7 +129,7 @@ class TorrentDetails(component.Component):
# We need to rename the tab in the state for backwards compat
self.state = [(tab_name.replace('Statistics', 'Status'), visible) for tab_name, visible in state]
for tab in default_tabs.itervalues():
for tab in default_tabs.values():
self.add_tab(tab(), generate_menu=False)
# Generate the checklist menu
@ -140,7 +140,7 @@ class TorrentDetails(component.Component):
# Determine insert position based on weight
# weights is a list of visible tab names in weight order
weights = sorted([(tab.weight, name) for name, tab in self.tabs.iteritems() if tab.is_visible])
weights = sorted([(tab.weight, name) for name, tab in self.tabs.items() if tab.is_visible])
log.debug('weights: %s', weights)
log.debug('weight of tab: %s', weight)
@ -219,7 +219,7 @@ class TorrentDetails(component.Component):
def hide_all_tabs(self):
"""Hides all tabs"""
log.debug('n_pages: %s', self.notebook.get_n_pages())
for n in xrange(self.notebook.get_n_pages() - 1, -1, -1):
for n in range(self.notebook.get_n_pages() - 1, -1, -1):
self.notebook.remove_page(n)
for tab in self.tabs:
@ -243,7 +243,7 @@ class TorrentDetails(component.Component):
self.generate_menu()
show = False
for name, tab in self.tabs.iteritems():
for name, tab in self.tabs.items():
show = show or tab.is_visible
self.visible(show)

View file

@ -413,7 +413,7 @@ class TorrentView(ListView, component.Component):
if columns is None:
# We need to iterate through all columns
columns = self.columns.keys()
columns = list(self.columns.keys())
# Iterate through supplied list of columns to update
for column in columns:
@ -486,7 +486,7 @@ class TorrentView(ListView, component.Component):
# Get the columns to update from one of the torrents
if status:
torrent_id = status.keys()[0]
torrent_id = list(status.keys())[0]
fields_to_update = []
for column in self.columns_to_update:
column_index = self.get_column_index(column)
@ -626,7 +626,7 @@ class TorrentView(ListView, component.Component):
return {}
def get_visible_torrents(self):
return self.status.keys()
return list(self.status.keys())
# Callbacks #
def on_button_press_event(self, widget, event):

View file

@ -92,7 +92,7 @@ class SessionProxy(component.Component):
keys_to_remove = keys_diff_cached
else:
# Not the same keys so create a new diff
keys_to_remove = set(sd[torrent_id].iterkeys()) - keys
keys_to_remove = set(sd[torrent_id]) - keys
# Update the cached diff
keys_diff_cached = keys_to_remove
keys_len = len(sd[torrent_id])
@ -180,7 +180,7 @@ class SessionProxy(component.Component):
def on_status(result, torrent_ids, keys):
# Update the internal torrent status dict with the update values
t = time()
for key, value in result.iteritems():
for key, value in result.items():
try:
self.torrents[key][0] = t
self.torrents[key][1].update(value)
@ -192,7 +192,7 @@ class SessionProxy(component.Component):
# Create the status dict
if not torrent_ids:
torrent_ids = result.keys()
torrent_ids = list(result.keys())
return self.create_status_dict(torrent_ids, keys)
@ -216,13 +216,13 @@ class SessionProxy(component.Component):
if not filter_dict:
# This means we want all the torrents status
# We get a list of any torrent_ids with expired status dicts
to_fetch = find_torrents_to_fetch(self.torrents.keys())
to_fetch = find_torrents_to_fetch(list(self.torrents.keys()))
if to_fetch:
d = client.core.get_torrents_status({'id': to_fetch}, keys, True)
return d.addCallback(on_status, self.torrents.keys(), keys)
return d.addCallback(on_status, list(self.torrents.keys()), keys)
# Don't need to fetch anything
return maybeDeferred(self.create_status_dict, self.torrents.keys(), keys)
return maybeDeferred(self.create_status_dict, list(self.torrents.keys()), keys)
if len(filter_dict) == 1 and 'id' in filter_dict:
# At this point we should have a filter with just "id" in it

View file

@ -9,6 +9,7 @@
from __future__ import unicode_literals
import __builtin__
import gettext
import locale
import logging
@ -22,7 +23,6 @@ log.addHandler(logging.NullHandler()) # Silence: No handlers could be found for
def set_dummy_trans(warn_msg=None):
import __builtin__
def _func(*txt):
if warn_msg:
@ -122,9 +122,7 @@ def setup_translations(setup_gettext=True, setup_pygtk=False):
gettext.bindtextdomain(domain, translations_path)
gettext.bind_textdomain_codeset(domain, 'UTF-8')
gettext.textdomain(domain)
gettext.install(domain, translations_path, unicode=True)
import __builtin__
__builtin__.__dict__['_n'] = gettext.ngettext
gettext.install(domain, translations_path)
except Exception as ex:
log.error('Unable to initialize gettext/locale!')
log.exception(ex)

View file

@ -90,7 +90,7 @@ class Auth(JSONComponent):
self.worker.stop()
def _clean_sessions(self):
session_ids = self.config['sessions'].keys()
session_ids = list(self.config['sessions'].keys())
now = time.gmtime()
for session_id in session_ids:

View file

@ -918,7 +918,7 @@ class WebApi(JSONComponent):
"""
return {
'enabled_plugins': component.get('Web.PluginManager').plugins.keys(),
'enabled_plugins': list(component.get('Web.PluginManager').plugins.keys()),
'available_plugins': component.get('Web.PluginManager').available_plugins
}

View file

@ -20,7 +20,8 @@ known_third_party =
# Ignore Windows specific modules.
bbfreeze, win32verstamp,
# Ignore gtk modules, primarily for tox testing.
pygtk, gtk, gobject, gtk.gdk, pango, cairo, pangocairo
pygtk, gtk, gobject, gtk.gdk, pango, cairo, pangocairo,
six
known_first_party = msgfmt, deluge
order_by_type = true
line_length = 120