[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
commit eb38e0ffff
64 changed files with 230 additions and 198 deletions

View file

@ -21,14 +21,20 @@ import re
import subprocess import subprocess
import sys import sys
import time import time
import urllib
import urlparse
import chardet import chardet
import pkg_resources import pkg_resources
from deluge.error import InvalidPathError 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 DBUS_FILEMAN = None
# gi makes dbus available on Window but don't import it as unused. # gi makes dbus available on Window but don't import it as unused.
if platform.system() not in ('Windows', 'Microsoft', 'Darwin'): if platform.system() not in ('Windows', 'Microsoft', 'Darwin'):
@ -56,6 +62,8 @@ TORRENT_STATE = [
'Moving' 'Moving'
] ]
PY2 = sys.version_info.major == 2
def get_version(): def get_version():
""" """
@ -82,12 +90,16 @@ def get_default_config_dir(filename=None):
def save_config_path(resource): def save_config_path(resource):
app_data_path = os.environ.get('APPDATA') app_data_path = os.environ.get('APPDATA')
if not app_data_path: if not app_data_path:
import _winreg try:
hkey = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, import winreg
'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders') except ImportError:
app_data_reg = _winreg.QueryValueEx(hkey, 'AppData') 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] app_data_path = app_data_reg[0]
_winreg.CloseKey(hkey) winreg.CloseKey(hkey)
return os.path.join(app_data_path, resource) return os.path.join(app_data_path, resource)
else: else:
from xdg.BaseDirectory import save_config_path from xdg.BaseDirectory import save_config_path
@ -241,7 +253,7 @@ def show_file(path, timestamp=None):
timestamp = int(time.time()) timestamp = int(time.time())
startup_id = '%s_%u_%s-dbus_TIME%d' % (os.path.basename(sys.argv[0]), os.getpid(), os.uname()[1], timestamp) startup_id = '%s_%u_%s-dbus_TIME%d' % (os.path.basename(sys.argv[0]), os.getpid(), os.uname()[1], timestamp)
if DBUS_FILEMAN: 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') DBUS_FILEMAN.ShowItems(paths, startup_id, dbus_interface='org.freedesktop.FileManager1')
else: else:
env = os.environ.copy() env = os.environ.copy()
@ -626,7 +638,7 @@ def get_magnet_info(uri):
else: else:
break break
elif param.startswith(dn_param): elif param.startswith(dn_param):
name = urllib.unquote_plus(param[len(dn_param):]) name = unquote_plus(param[len(dn_param):])
if info_hash: if info_hash:
if not name: if not name:
@ -837,9 +849,9 @@ def utf8_encode_structure(data):
""" """
if isinstance(data, (list, tuple)): 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): 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): elif not isinstance(data, bytes):
try: try:
return data.encode('utf8') return data.encode('utf8')
@ -1048,7 +1060,7 @@ def unicode_argv():
# Remove Python executable and commands if present # Remove Python executable and commands if present
start = argc.value - len(sys.argv) start = argc.value - len(sys.argv)
return [argv[i] for i in return [argv[i] for i in
xrange(start, argc.value)] range(start, argc.value)]
else: else:
# On other platforms, we have to find the likely encoding of the args and decode # 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 # 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.defer import DeferredList, fail, maybeDeferred, succeed
from twisted.internet.task import LoopingCall, deferLater from twisted.internet.task import LoopingCall, deferLater
from deluge.common import PY2
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -307,7 +309,7 @@ class ComponentRegistry(object):
# Start all the components if names is empty # Start all the components if names is empty
if not names: if not names:
names = self.components.keys() names = self.components.keys()
elif not isinstance(names, (list, tuple)): elif isinstance(names, str if not PY2 else basestring):
names = [names] names = [names]
def on_depends_started(result, name): def on_depends_started(result, name):
@ -341,7 +343,7 @@ class ComponentRegistry(object):
""" """
if not names: if not names:
names = self.components.keys() names = self.components.keys()
elif not isinstance(names, (list, tuple)): elif isinstance(names, str if not PY2 else basestring):
names = [names] names = [names]
def on_dependents_stopped(result, name): def on_dependents_stopped(result, name):
@ -379,7 +381,7 @@ class ComponentRegistry(object):
""" """
if not names: if not names:
names = self.components.keys() names = self.components.keys()
elif not isinstance(names, (list, tuple)): elif isinstance(names, str if not PY2 else basestring):
names = [names] names = [names]
deferreds = [] deferreds = []
@ -405,7 +407,7 @@ class ComponentRegistry(object):
""" """
if not names: if not names:
names = self.components.keys() names = self.components.keys()
elif not isinstance(names, (list, tuple)): elif isinstance(names, str if not PY2 else basestring):
names = [names] names = [names]
deferreds = [] deferreds = []
@ -429,7 +431,7 @@ class ComponentRegistry(object):
def on_stopped(result): def on_stopped(result):
return DeferredList([comp._component_shutdown() for comp in self.components.values()]) 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): def update(self):
"""Update all Components that are in a Started state.""" """Update all Components that are in a Started state."""

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -159,7 +159,7 @@ class TorrentOptions(dict):
'stop_ratio': 'stop_seed_ratio', 'stop_ratio': 'stop_seed_ratio',
'super_seeding': 'super_seeding' '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[opt_k] = config[conf_k]
self['file_priorities'] = [] self['file_priorities'] = []
self['mapped_files'] = {} self['mapped_files'] = {}
@ -924,7 +924,7 @@ class Torrent(object):
self.update_status(self.handle.status()) self.update_status(self.handle.status())
if all_keys: if all_keys:
keys = self.status_funcs.keys() keys = self.status_funcs
status_dict = {} 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] 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,)) 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) d.addBoth(on_folder_rename_complete, self, folder, new_folder)
return d return d

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -134,7 +134,7 @@ class Core(CorePluginBase):
def disable(self): def disable(self):
self.config.save() self.config.save()
event_manager = component.get('EventManager') 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) event_manager.deregister_event_handler(event, handler)
log.debug('Execute core plugin disabled!') log.debug('Execute core plugin disabled!')

View file

@ -40,14 +40,18 @@ if windows_check():
'C:\\Program Files (x86)\\7-Zip\\7z.exe', 'C:\\Program Files (x86)\\7-Zip\\7z.exe',
] ]
import _winreg
try: 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: except WindowsError:
pass pass
else: else:
win_7z_path = os.path.join(_winreg.QueryValueEx(hkey, 'Path')[0], '7z.exe') win_7z_path = os.path.join(winreg.QueryValueEx(hkey, 'Path')[0], '7z.exe')
_winreg.CloseKey(hkey) winreg.CloseKey(hkey)
win_7z_exes.insert(1, win_7z_path) win_7z_exes.insert(1, win_7z_path)
switch_7z = 'x -y' switch_7z = 'x -y'

View file

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

View file

@ -174,7 +174,7 @@ class OptionsDialog(object):
self.dialog.run() self.dialog.run()
def load_options(self, options): 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: for spin_id in self.spin_ids + self.spin_int_ids:
self.glade.get_widget(spin_id).set_value(options[spin_id]) 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 twisted.internet import defer
from deluge import component from deluge import component
from deluge.event import known_events
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
try:
from deluge.event import known_events
except ImportError:
# Old deluge version
known_events = {}
def get_resource(filename): def get_resource(filename):
import os import os
@ -49,8 +44,8 @@ class CustomNotifications(object):
pass pass
def disable(self): def disable(self):
for kind in self.custom_notifications.iterkeys(): for kind in self.custom_notifications:
for eventtype in self.custom_notifications[kind].copy().iterkeys(): for eventtype in list(self.custom_notifications[kind]):
wrapper, handler = self.custom_notifications[kind][eventtype] wrapper, handler = self.custom_notifications[kind][eventtype]
self._deregister_custom_provider(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_EVENT, SUB_EVENT_DOC, SUB_NOT_EMAIL, SUB_NOT_POPUP, SUB_NOT_BLINK,
SUB_NOT_SOUND) = range(6) SUB_NOT_SOUND) = list(range(6))
SND_EVENT, SND_EVENT_DOC, SND_NAME, SND_PATH = range(4) SND_EVENT, SND_EVENT_DOC, SND_NAME, SND_PATH = list(range(4))
class GtkUiNotifications(CustomNotifications): class GtkUiNotifications(CustomNotifications):

View file

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

View file

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

View file

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

View file

@ -135,7 +135,7 @@ class Graph(object):
# this doesnt allow for dst and timezones... # this doesnt allow for dst and timezones...
seconds_to_step = math.ceil(start / x_step) * x_step - start 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)) text = time.strftime('%H:%M', time.localtime(start + seconds_to_step + i * x_step))
# + 0.5 to allign x to nearest pixel # + 0.5 to allign x to nearest pixel
x = int(ratio * (seconds_to_step + i * x_step) + left) + 0.5 x = int(ratio * (seconds_to_step + i * x_step) + left) + 0.5
@ -220,7 +220,7 @@ class Graph(object):
else: else:
interval = interval * 2 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 return intervals
def draw_left_axis(self, bounds, y_ticks, y_tick_text): 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_y_text(y_tick_text[i], left, y)
self.draw_line(gray, left, top, left, bottom) 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: if len(info['values']) > 0:
self.draw_value_poly(info['values'], info['color'], max_value, bounds) 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']) 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 return False
def update(self): 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) d1.addCallback(self.graph.set_stats)
def _update_complete(result): def _update_complete(result):

View file

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

View file

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

View file

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

View file

@ -187,7 +187,7 @@ class RPCRaiseDelugeErrorJSONTestCase(JSONBase):
self.assertTrue('testclass.test' in methods) self.assertTrue('testclass.test' in methods)
request = MagicMock() 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': []} json_data = {'method': 'testclass.test', 'id': 0, 'params': []}
request.json = json_lib.dumps(json_data) request.json = json_lib.dumps(json_data)
request_id, result, error = json._handle_request(request) 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): def get_torrent_status(self, torrent_id, keys, diff=False):
if not keys: if not keys:
keys = self.torrents[torrent_id].keys() keys = list(self.torrents[torrent_id].keys())
if not diff: if not diff:
ret = {} ret = {}
@ -57,9 +57,9 @@ class Core(object):
def get_torrents_status(self, filter_dict, keys, diff=False): def get_torrents_status(self, filter_dict, keys, diff=False):
if not filter_dict: if not filter_dict:
filter_dict['id'] = self.torrents.keys() filter_dict['id'] = list(self.torrents.keys())
if not keys: if not keys:
keys = self.torrents['a'].keys() keys = list(self.torrents['a'].keys())
if not diff: if not diff:
if 'id' in filter_dict: if 'id' in filter_dict:
torrents = filter_dict['id'] torrents = filter_dict['id']

View file

@ -152,7 +152,7 @@ class GtkUIBaseTestCase(UIBaseTestCase):
"""Implement all GtkUI tests here""" """Implement all GtkUI tests here"""
def test_start_gtkui(self): 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 from deluge.ui.gtkui import gtkui
with mock.patch.object(gtkui.GtkUI, 'start', autospec=True): 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['cmd_name'] = 'deluge gtk'
self.var['start_cmd'] = ui_entry.start_ui 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): def set_up(self):
return GtkUIBaseTestCase.set_up(self) return GtkUIBaseTestCase.set_up(self)

View file

@ -48,6 +48,7 @@ from __future__ import division, unicode_literals
import logging import logging
import struct import struct
from future_builtins import zip
import PIL.BmpImagePlugin import PIL.BmpImagePlugin
import PIL.Image import PIL.Image
@ -77,9 +78,9 @@ class Win32IcoFile(object):
self.nb_items = header[2] self.nb_items = header[2]
dir_fields = ('width', 'height', 'nb_color', 'reserved', 'planes', 'bpp', 'size', 'offset') 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))) directory = list(struct.unpack('<4B2H2I', buf.read(16)))
for j in xrange(3): for j in range(3):
if not directory[j]: if not directory[j]:
directory[j] = 256 directory[j] = 256
icon_header = dict(zip(dir_fields, directory)) 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 # We need to tell the daemon what events we're interested in receiving
if self.__factory.event_handlers: if self.__factory.event_handlers:
self.call('daemon.set_event_interest', 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.call('core.get_auth_levels_mappings').addCallback(
self.__on_auth_levels_mappings self.__on_auth_levels_mappings

View file

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

View file

@ -12,8 +12,6 @@ from __future__ import unicode_literals
import base64 import base64
import os import os
from urllib import url2pathname
from urlparse import urlparse
from twisted.internet import defer from twisted.internet import defer
@ -23,6 +21,14 @@ from deluge.ui.client import client
from . import BaseCommand 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): class Command(BaseCommand):
"""Add torrents""" """Add torrents"""

View file

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

View file

@ -147,7 +147,7 @@ class Command(BaseCommand):
self.console.write('{!error!}Unknown sort key: ' + sort_key + ', will sort on name') self.console.write('{!error!}Unknown sort key: ' + sort_key + ', will sort on name')
sort_key = 'name' sort_key = 'name'
sort_reverse = False 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) self.show_info(key, status[key], options.verbose, options.detailed)
def on_torrents_status_fail(reason): def on_torrents_status_fail(reason):

View file

@ -12,6 +12,7 @@ from __future__ import unicode_literals
import base64 import base64
import logging import logging
import os import os
from future_builtins import zip
import deluge.common import deluge.common
import deluge.component as component import deluge.component as component
@ -513,9 +514,9 @@ class AddTorrents(BaseMode):
elif chr(c) == 'M': elif chr(c) == 'M':
if self.last_mark != -1: if self.last_mark != -1:
if self.last_mark > self.cursel: if self.last_mark > self.cursel:
m = range(self.cursel, self.last_mark) m = list(range(self.cursel, self.last_mark))
else: else:
m = range(self.last_mark, self.cursel + 1) m = list(range(self.last_mark, self.cursel + 1))
for i in m: for i in m:
s = self.raw_rows[i][0] 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): class ZONE(object):
length = 3 length = 3
CATEGORIES, PREFRENCES, ACTIONS = range(length) CATEGORIES, PREFRENCES, ACTIONS = list(range(length))
class PreferenceSidebar(Sidebar): class PreferenceSidebar(Sidebar):

View file

@ -79,7 +79,7 @@ class QueueMode(object):
self.torrentview.cursel = 1 + sorted(self.torrentview.marked).index(self.torrentview.cursel) self.torrentview.cursel = 1 + sorted(self.torrentview.marked).index(self.torrentview.cursel)
else: else:
self.torrentview.cursel = 1 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: elif qact == ACTION.QUEUE_UP:
self.torrentview.cursel = max(1, self.torrentview.cursel - 1) self.torrentview.cursel = max(1, self.torrentview.cursel - 1)
self.torrentview.marked = [marked - 1 for marked in self.torrentview.marked] 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)) sorted(self.torrentview.marked).index(self.torrentview.cursel))
else: else:
self.torrentview.cursel = queue_length 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): def do_queue(self, qact, *args, **kwargs):
if qact == ACTION.QUEUE_TOP: 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): def _do_set_torrent_options(torrent_ids, result):
options = {} options = {}
for opt, val in result.iteritems(): for opt, val in result.items():
if val['value'] not in ['multiple', None]: if val['value'] not in ['multiple', None]:
options[opt] = val['value'] options[opt] = val['value']
client.core.set_torrent_options(torrent_ids, options) 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 # Get first element so we can check if it has given field
# and if it's a string # and if it's a string
first_element = state[state.keys()[0]] first_element = state[list(state.keys())[0]]
if field in first_element: if field in first_element:
def sort_key(s): def sort_key(s):
try: try:
@ -449,9 +449,9 @@ class TorrentView(InputKeyHandler):
elif c == ord('M'): elif c == ord('M'):
if self.last_mark >= 0: if self.last_mark >= 0:
if self.cursel > self.last_mark: if self.cursel > self.last_mark:
mrange = range(self.last_mark, self.cursel + 1) mrange = list(range(self.last_mark, self.cursel + 1))
else: else:
mrange = range(self.cursel, self.last_mark) mrange = list(range(self.cursel, self.last_mark))
self.add_marked(mrange, self.cursel) self.add_marked(mrange, self.cursel)
affected_lines = mrange affected_lines = mrange
else: else:

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -15,8 +15,6 @@ import os
import sys import sys
from glob import glob from glob import glob
from tempfile import mkstemp from tempfile import mkstemp
from urllib import url2pathname
from urlparse import urlparse
import twisted.internet.error import twisted.internet.error
from twisted.internet import reactor from twisted.internet import reactor
@ -32,6 +30,14 @@ try:
except ImportError: except ImportError:
import deluge.rencode as rencode # pylint: disable=ungrouped-imports 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__) log = logging.getLogger(__name__)

View file

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

View file

@ -39,7 +39,7 @@ class _GtkBuilderSignalsHolder(object):
def connect_signals(self, mapping_or_class): def connect_signals(self, mapping_or_class):
if isinstance(mapping_or_class, dict): 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): if hasattr(self, name):
raise RuntimeError( raise RuntimeError(
'A handler for signal %r has already been registered: %s' % '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_max_connections': 'max_connections',
'menuitem_upload_slots': 'max_upload_slots' '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() torrent_ids = component.get('TorrentView').get_selected_torrents()
client.core.set_torrent_options(torrent_ids, {funcs[widget.get_name()]: -1}) client.core.set_torrent_options(torrent_ids, {funcs[widget.get_name()]: -1})
@ -494,7 +494,7 @@ class MenuBar(component.Component):
known_accounts_to_log = [] known_accounts_to_log = []
for account in known_accounts: for account in known_accounts:
account_to_log = {} account_to_log = {}
for key, value in account.copy().iteritems(): for key, value in account.copy().items():
if key == 'password': if key == 'password':
value = '*' * len(value) value = '*' * len(value)
account_to_log[key] = value account_to_log[key] = value
@ -537,7 +537,7 @@ class MenuBar(component.Component):
return return
torrent_owner = component.get('TorrentView').get_torrent_status(selected[0])['owner'] 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) item.set_active(username == torrent_owner)
def _on_change_owner_toggled(self, widget, username): 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 # 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. # is so we don't overwrite the user changes that haven't been applied yet.
if self.prev_status is None: 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 != self.prev_status:
if status['max_download_speed'] != self.prev_status['max_download_speed']: 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) self.config_properties.update(config)
for chooser in self.path_choosers: for chooser in self.path_choosers:
chooser.set_config(config) 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 keys += self.paths_list_keys
client.core.get_config_values(keys).addCallback(_on_config_values) client.core.get_config_values(keys).addCallback(_on_config_values)
@ -109,7 +109,7 @@ class PathChoosersHandler(component.Component):
chooser.set_values(values) chooser.set_values(values)
def get_config_keys(self): 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 keys += self.paths_list_keys
return keys return keys

View file

@ -36,8 +36,8 @@ except ImportError:
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
ACCOUNTS_USERNAME, ACCOUNTS_LEVEL, ACCOUNTS_PASSWORD = range(3) ACCOUNTS_USERNAME, ACCOUNTS_LEVEL, ACCOUNTS_PASSWORD = list(range(3))
COLOR_MISSING, COLOR_WAITING, COLOR_DOWNLOADING, COLOR_COMPLETED = range(4) COLOR_MISSING, COLOR_WAITING, COLOR_DOWNLOADING, COLOR_COMPLETED = list(range(4))
COLOR_STATES = { COLOR_STATES = {
'missing': COLOR_MISSING, 'missing': COLOR_MISSING,
@ -1020,7 +1020,7 @@ class Preferences(component.Component):
known_accounts_to_log = [] known_accounts_to_log = []
for account in known_accounts: for account in known_accounts:
account_to_log = {} account_to_log = {}
for key, value in account.copy().iteritems(): for key, value in account.copy().items():
if key == 'password': if key == 'password':
value = '*' * len(value) value = '*' * len(value)
account_to_log[key] = 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 This is called when we receive a ConfigValueChangedEvent from
the core. 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) self.config_value_changed_dict[key](value)
def _on_max_connections_global(self, max_connections): 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): def config_value_changed(self, key, value):
"""This is called when we received a config_value_changed signal from """This is called when we received a config_value_changed signal from
the core.""" 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) self.config_value_changed_dict[key](value)
def _on_max_download_speed(self, max_download_speed): 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 # 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] 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) self.add_tab(tab(), generate_menu=False)
# Generate the checklist menu # Generate the checklist menu
@ -140,7 +140,7 @@ class TorrentDetails(component.Component):
# Determine insert position based on weight # Determine insert position based on weight
# weights is a list of visible tab names in weight order # 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('weights: %s', weights)
log.debug('weight of tab: %s', weight) log.debug('weight of tab: %s', weight)
@ -219,7 +219,7 @@ class TorrentDetails(component.Component):
def hide_all_tabs(self): def hide_all_tabs(self):
"""Hides all tabs""" """Hides all tabs"""
log.debug('n_pages: %s', self.notebook.get_n_pages()) 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) self.notebook.remove_page(n)
for tab in self.tabs: for tab in self.tabs:
@ -243,7 +243,7 @@ class TorrentDetails(component.Component):
self.generate_menu() self.generate_menu()
show = False show = False
for name, tab in self.tabs.iteritems(): for name, tab in self.tabs.items():
show = show or tab.is_visible show = show or tab.is_visible
self.visible(show) self.visible(show)

View file

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

View file

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

View file

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

View file

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

View file

@ -918,7 +918,7 @@ class WebApi(JSONComponent):
""" """
return { 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 'available_plugins': component.get('Web.PluginManager').available_plugins
} }

View file

@ -20,7 +20,8 @@ known_third_party =
# Ignore Windows specific modules. # Ignore Windows specific modules.
bbfreeze, win32verstamp, bbfreeze, win32verstamp,
# Ignore gtk modules, primarily for tox testing. # 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 known_first_party = msgfmt, deluge
order_by_type = true order_by_type = true
line_length = 120 line_length = 120