[Core] Implement async_add_torrent in torrentmanager
This commit is contained in:
parent
73220b5116
commit
5d1aff157e
|
@ -50,11 +50,10 @@ class AlertManager(component.Component):
|
||||||
# handlers is a dictionary of lists {"alert_type": [handler1,h2,..]}
|
# handlers is a dictionary of lists {"alert_type": [handler1,h2,..]}
|
||||||
self.handlers = {}
|
self.handlers = {}
|
||||||
self.delayed_calls = []
|
self.delayed_calls = []
|
||||||
self.wait_on_handler = False
|
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
self.delayed_calls = [dc for dc in self.delayed_calls if dc.active()]
|
self.delayed_calls = [dc for dc in self.delayed_calls if dc.active()]
|
||||||
self.handle_alerts(wait=self.wait_on_handler)
|
self.handle_alerts()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
for delayed_call in self.delayed_calls:
|
for delayed_call in self.delayed_calls:
|
||||||
|
@ -92,12 +91,9 @@ class AlertManager(component.Component):
|
||||||
# Handler is in this alert type list
|
# Handler is in this alert type list
|
||||||
value.remove(handler)
|
value.remove(handler)
|
||||||
|
|
||||||
def handle_alerts(self, wait=False):
|
def handle_alerts(self):
|
||||||
"""Pops all libtorrent alerts in the session queue and handles them appropriately.
|
"""
|
||||||
|
Pops all libtorrent alerts in the session queue and handles them appropriately.
|
||||||
Args:
|
|
||||||
wait (bool): If True the handler functions will be run straight away and
|
|
||||||
waited to return before processing the next alert.
|
|
||||||
"""
|
"""
|
||||||
alerts = self.session.pop_alerts()
|
alerts = self.session.pop_alerts()
|
||||||
if not alerts:
|
if not alerts:
|
||||||
|
@ -118,10 +114,7 @@ class AlertManager(component.Component):
|
||||||
# Call any handlers for this alert type
|
# Call any handlers for this alert type
|
||||||
if alert_type in self.handlers:
|
if alert_type in self.handlers:
|
||||||
for handler in self.handlers[alert_type]:
|
for handler in self.handlers[alert_type]:
|
||||||
if not wait:
|
self.delayed_calls.append(reactor.callLater(0, handler, alert))
|
||||||
self.delayed_calls.append(reactor.callLater(0, handler, alert))
|
|
||||||
else:
|
|
||||||
handler(alert)
|
|
||||||
|
|
||||||
def set_alert_queue_size(self, queue_size):
|
def set_alert_queue_size(self, queue_size):
|
||||||
"""Sets the maximum size of the libtorrent alert queue"""
|
"""Sets the maximum size of the libtorrent alert queue"""
|
||||||
|
|
|
@ -16,7 +16,7 @@ import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
from twisted.internet import reactor, task
|
from twisted.internet import defer, reactor, task
|
||||||
from twisted.web.client import getPage
|
from twisted.web.client import getPage
|
||||||
|
|
||||||
import deluge.common
|
import deluge.common
|
||||||
|
@ -33,7 +33,7 @@ from deluge.core.pluginmanager import PluginManager
|
||||||
from deluge.core.preferencesmanager import PreferencesManager
|
from deluge.core.preferencesmanager import PreferencesManager
|
||||||
from deluge.core.rpcserver import export
|
from deluge.core.rpcserver import export
|
||||||
from deluge.core.torrentmanager import TorrentManager
|
from deluge.core.torrentmanager import TorrentManager
|
||||||
from deluge.error import DelugeError, InvalidPathError, InvalidTorrentError
|
from deluge.error import AddTorrentError, DelugeError, InvalidPathError, InvalidTorrentError
|
||||||
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
|
||||||
|
|
||||||
|
@ -211,13 +211,14 @@ class Core(component.Component):
|
||||||
log.error("There was an error decoding the filedump string: %s", ex)
|
log.error("There was an error decoding the filedump string: %s", ex)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
torrent_id = self.torrentmanager.add(
|
d = self.torrentmanager.add(
|
||||||
filedump=filedump, options=options, filename=filename, save_state=save_state
|
filedump=filedump, options=options, filename=filename, save_state=save_state
|
||||||
)
|
)
|
||||||
except RuntimeError as ex:
|
except RuntimeError as ex:
|
||||||
log.error("There was an error adding the torrent file %s: %s", filename, ex)
|
log.error("There was an error adding the torrent file %s: %s", filename, ex)
|
||||||
torrent_id = None
|
raise
|
||||||
return torrent_id
|
else:
|
||||||
|
return d
|
||||||
|
|
||||||
# Exported Methods
|
# Exported Methods
|
||||||
@export
|
@export
|
||||||
|
@ -246,14 +247,18 @@ class Core(component.Component):
|
||||||
Deferred
|
Deferred
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@defer.inlineCallbacks
|
||||||
def add_torrents():
|
def add_torrents():
|
||||||
torrent_ids = []
|
errors = []
|
||||||
count = len(torrent_files)
|
last_index = len(torrent_files) - 1
|
||||||
for idx, torrent in enumerate(torrent_files):
|
for idx, torrent in enumerate(torrent_files):
|
||||||
torrent_id = self._add_torrent_file(torrent[0], torrent[1],
|
try:
|
||||||
torrent[2], save_state=idx == (count - 1))
|
yield self._add_torrent_file(torrent[0], torrent[1],
|
||||||
torrent_ids.append(torrent_id)
|
torrent[2], save_state=idx == last_index)
|
||||||
return torrent_ids
|
except AddTorrentError as ex:
|
||||||
|
log.warn("Error when adding torrent: '%s'", ex)
|
||||||
|
errors.append(ex)
|
||||||
|
defer.returnValue(errors)
|
||||||
return task.deferLater(reactor, 0, add_torrents)
|
return task.deferLater(reactor, 0, add_torrents)
|
||||||
|
|
||||||
@export
|
@export
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
"""TorrentManager handles Torrent objects"""
|
"""TorrentManager handles Torrent objects"""
|
||||||
|
|
||||||
import cPickle
|
import cPickle
|
||||||
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import operator
|
import operator
|
||||||
import os
|
import os
|
||||||
|
@ -26,7 +27,7 @@ from deluge.common import decode_string, get_magnet_info, utf8_encoded
|
||||||
from deluge.configmanager import ConfigManager, get_config_dir
|
from deluge.configmanager import ConfigManager, get_config_dir
|
||||||
from deluge.core.authmanager import AUTH_LEVEL_ADMIN
|
from deluge.core.authmanager import AUTH_LEVEL_ADMIN
|
||||||
from deluge.core.torrent import Torrent, TorrentOptions, sanitize_filepath
|
from deluge.core.torrent import Torrent, TorrentOptions, sanitize_filepath
|
||||||
from deluge.error import InvalidTorrentError
|
from deluge.error import AddTorrentError, InvalidTorrentError
|
||||||
from deluge.event import (PreTorrentRemovedEvent, SessionStartedEvent, TorrentAddedEvent, TorrentFileCompletedEvent,
|
from deluge.event import (PreTorrentRemovedEvent, SessionStartedEvent, TorrentAddedEvent, TorrentFileCompletedEvent,
|
||||||
TorrentFileRenamedEvent, TorrentFinishedEvent, TorrentRemovedEvent, TorrentResumedEvent)
|
TorrentFileRenamedEvent, TorrentFinishedEvent, TorrentRemovedEvent, TorrentResumedEvent)
|
||||||
|
|
||||||
|
@ -105,6 +106,7 @@ class TorrentManager(component.Component):
|
||||||
self.torrents = {}
|
self.torrents = {}
|
||||||
self.queued_torrents = set()
|
self.queued_torrents = set()
|
||||||
self.is_saving_state = False
|
self.is_saving_state = False
|
||||||
|
self.torrents_loading = {}
|
||||||
|
|
||||||
# This is a map of torrent_ids to Deferreds used to track needed resume data.
|
# This is a map of torrent_ids to Deferreds used to track needed resume data.
|
||||||
# The Deferreds will be completed when resume data has been saved.
|
# The Deferreds will be completed when resume data has been saved.
|
||||||
|
@ -152,6 +154,7 @@ class TorrentManager(component.Component):
|
||||||
self.alerts.register_handler("external_ip_alert", self.on_alert_external_ip)
|
self.alerts.register_handler("external_ip_alert", self.on_alert_external_ip)
|
||||||
self.alerts.register_handler("performance_alert", self.on_alert_performance)
|
self.alerts.register_handler("performance_alert", self.on_alert_performance)
|
||||||
self.alerts.register_handler("fastresume_rejected_alert", self.on_alert_fastresume_rejected)
|
self.alerts.register_handler("fastresume_rejected_alert", self.on_alert_fastresume_rejected)
|
||||||
|
self.alerts.register_handler("add_torrent_alert", self.on_add_torrent_alert)
|
||||||
|
|
||||||
# Define timers
|
# Define timers
|
||||||
self.save_state_timer = LoopingCall(self.save_state)
|
self.save_state_timer = LoopingCall(self.save_state)
|
||||||
|
@ -163,7 +166,6 @@ class TorrentManager(component.Component):
|
||||||
if os.path.isfile(self.temp_file):
|
if os.path.isfile(self.temp_file):
|
||||||
def archive_file(filename):
|
def archive_file(filename):
|
||||||
"""Archives the file in 'archive' sub-directory with timestamp appended"""
|
"""Archives the file in 'archive' sub-directory with timestamp appended"""
|
||||||
import datetime
|
|
||||||
filepath = os.path.join(self.state_dir, filename)
|
filepath = os.path.join(self.state_dir, filename)
|
||||||
filepath_bak = filepath + ".bak"
|
filepath_bak = filepath + ".bak"
|
||||||
archive_dir = os.path.join(get_config_dir(), "archive")
|
archive_dir = os.path.join(get_config_dir(), "archive")
|
||||||
|
@ -302,16 +304,14 @@ class TorrentManager(component.Component):
|
||||||
TorrentAddedEvent: Torrent with torrent_id added to session.
|
TorrentAddedEvent: Torrent with torrent_id added to session.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if torrent_info is None and filedump is None and magnet is None:
|
if not torrent_info and not filedump and not magnet:
|
||||||
log.error("You must specify a valid torrent_info, torrent state or magnet.")
|
raise AddTorrentError("You must specify a valid torrent_info, torrent state or magnet.")
|
||||||
return
|
|
||||||
|
|
||||||
if filedump:
|
if filedump:
|
||||||
try:
|
try:
|
||||||
torrent_info = lt.torrent_info(lt.bdecode(filedump))
|
torrent_info = lt.torrent_info(lt.bdecode(filedump))
|
||||||
except RuntimeError as ex:
|
except RuntimeError as ex:
|
||||||
log.error("Unable to add torrent, decoding filedump failed: %s", ex)
|
raise AddTorrentError("Unable to add torrent, decoding filedump failed: %s" % ex)
|
||||||
return
|
|
||||||
|
|
||||||
add_torrent_params = {}
|
add_torrent_params = {}
|
||||||
if torrent_info:
|
if torrent_info:
|
||||||
|
@ -329,15 +329,15 @@ class TorrentManager(component.Component):
|
||||||
add_torrent_params["name"] = magnet_info["name"]
|
add_torrent_params["name"] = magnet_info["name"]
|
||||||
torrent_id = magnet_info["info_hash"]
|
torrent_id = magnet_info["info_hash"]
|
||||||
else:
|
else:
|
||||||
log.error("Unable to add magnet, invalid magnet info: %s", magnet)
|
raise AddTorrentError("Unable to add magnet, invalid magnet info: %s" % magnet)
|
||||||
return
|
|
||||||
|
|
||||||
# Check for existing torrent in session.
|
# Check for existing torrent in session.
|
||||||
if torrent_id in self.get_torrent_list():
|
if torrent_id in self.get_torrent_list():
|
||||||
log.warning("Unable to add torrent (%s), already in session", torrent_id)
|
|
||||||
# Attempt merge trackers before returning.
|
# Attempt merge trackers before returning.
|
||||||
self.torrents[torrent_id].merge_trackers(torrent_info)
|
self.torrents[torrent_id].merge_trackers(torrent_info)
|
||||||
return
|
raise AddTorrentError("Torrent already in session (%s)." % torrent_id)
|
||||||
|
elif torrent_id in self.torrents_loading:
|
||||||
|
raise AddTorrentError("Torrent already being added (%s)." % torrent_id)
|
||||||
|
|
||||||
# Load default options and update if needed.
|
# Load default options and update if needed.
|
||||||
_options = TorrentOptions()
|
_options = TorrentOptions()
|
||||||
|
@ -385,24 +385,31 @@ class TorrentManager(component.Component):
|
||||||
if options["seed_mode"]:
|
if options["seed_mode"]:
|
||||||
add_torrent_params["flags"] |= lt.add_torrent_params_flags_t.flag_seed_mode
|
add_torrent_params["flags"] |= lt.add_torrent_params_flags_t.flag_seed_mode
|
||||||
|
|
||||||
# We need to pause the AlertManager momentarily to prevent alerts
|
d = Deferred()
|
||||||
# for this torrent being generated before a Torrent object is created.
|
|
||||||
component.pause("AlertManager")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
handle = self.session.add_torrent(add_torrent_params)
|
self.torrents_loading[torrent_id] = (d, options, state, filename, magnet, resume_data, filedump, save_state)
|
||||||
if not handle.is_valid():
|
self.session.async_add_torrent(add_torrent_params)
|
||||||
raise InvalidTorrentError("Torrent handle is invalid!")
|
except RuntimeError as ex:
|
||||||
except (RuntimeError, InvalidTorrentError) as ex:
|
raise AddTorrentError("Unable to add torrent to session: %s" % ex)
|
||||||
log.error("Unable to add torrent to session: %s", ex)
|
return d
|
||||||
component.resume("AlertManager")
|
|
||||||
|
def on_add_torrent_alert(self, alert):
|
||||||
|
"""Alert handler for libtorrent add_torrent_alert"""
|
||||||
|
if not alert.handle.is_valid():
|
||||||
|
log.warn("Torrent handle is invalid!")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Create a Torrent object and add to the dictionary.
|
try:
|
||||||
torrent = Torrent(handle, options, state, filename, magnet)
|
torrent_id = str(alert.handle.info_hash())
|
||||||
self.torrents[torrent.torrent_id] = torrent
|
except RuntimeError as ex:
|
||||||
|
log.warn("Failed to get torrent id from handle: %s", ex)
|
||||||
|
return
|
||||||
|
|
||||||
component.resume("AlertManager")
|
d, options, state, filename, magnet, resume_data, filedump, save_state = self.torrents_loading.pop(torrent_id)
|
||||||
|
|
||||||
|
# Create a Torrent object and add to the dictionary.
|
||||||
|
torrent = Torrent(alert.handle, options, state, filename, magnet)
|
||||||
|
self.torrents[torrent.torrent_id] = torrent
|
||||||
|
|
||||||
# Store the orignal resume_data, in case of errors.
|
# Store the orignal resume_data, in case of errors.
|
||||||
if resume_data:
|
if resume_data:
|
||||||
|
@ -422,7 +429,7 @@ class TorrentManager(component.Component):
|
||||||
component.get("EventManager").emit(TorrentAddedEvent(torrent.torrent_id, from_state))
|
component.get("EventManager").emit(TorrentAddedEvent(torrent.torrent_id, from_state))
|
||||||
|
|
||||||
if log.isEnabledFor(logging.DEBUG):
|
if log.isEnabledFor(logging.DEBUG):
|
||||||
log.debug("Torrent added: %s", str(handle.info_hash()))
|
log.debug("Torrent added: %s", str(alert.handle.info_hash()))
|
||||||
if log.isEnabledFor(logging.INFO):
|
if log.isEnabledFor(logging.INFO):
|
||||||
name_and_owner = torrent.get_status(["name", "owner"])
|
name_and_owner = torrent.get_status(["name", "owner"])
|
||||||
log.info("Torrent %s from user \"%s\" %s",
|
log.info("Torrent %s from user \"%s\" %s",
|
||||||
|
@ -438,7 +445,7 @@ class TorrentManager(component.Component):
|
||||||
if save_state:
|
if save_state:
|
||||||
self.save_state()
|
self.save_state()
|
||||||
|
|
||||||
return torrent.torrent_id
|
d.callback(torrent.torrent_id)
|
||||||
|
|
||||||
def remove(self, torrent_id, remove_data=False, save_state=True):
|
def remove(self, torrent_id, remove_data=False, save_state=True):
|
||||||
"""Remove a torrent from the session.
|
"""Remove a torrent from the session.
|
||||||
|
@ -556,6 +563,7 @@ class TorrentManager(component.Component):
|
||||||
SessionStartedEvent: Emitted after all torrents are added to the session.
|
SessionStartedEvent: Emitted after all torrents are added to the session.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
start = datetime.datetime.now()
|
||||||
state = self.open_state()
|
state = self.open_state()
|
||||||
state = self.fixup_state(state)
|
state = self.fixup_state(state)
|
||||||
|
|
||||||
|
@ -563,10 +571,7 @@ class TorrentManager(component.Component):
|
||||||
state.torrents.sort(key=operator.attrgetter("queue"), reverse=self.config["queue_new_to_top"])
|
state.torrents.sort(key=operator.attrgetter("queue"), reverse=self.config["queue_new_to_top"])
|
||||||
resume_data = self.load_resume_data_file()
|
resume_data = self.load_resume_data_file()
|
||||||
|
|
||||||
# Tell alertmanager to wait for the handlers while adding torrents.
|
deferreds = []
|
||||||
# This speeds up startup loading the torrents by quite a lot for some reason (~40%)
|
|
||||||
self.alerts.wait_on_handler = True
|
|
||||||
|
|
||||||
for t_state in state.torrents:
|
for t_state in state.torrents:
|
||||||
# Populate the options dict from state
|
# Populate the options dict from state
|
||||||
options = TorrentOptions()
|
options = TorrentOptions()
|
||||||
|
@ -587,12 +592,16 @@ class TorrentManager(component.Component):
|
||||||
if torrent_info:
|
if torrent_info:
|
||||||
magnet = None
|
magnet = None
|
||||||
|
|
||||||
self.add(torrent_info=torrent_info, state=t_state, options=options, save_state=False,
|
d = self.add(torrent_info=torrent_info, state=t_state, options=options, save_state=False,
|
||||||
magnet=magnet, resume_data=resume_data.get(t_state.torrent_id))
|
magnet=magnet, resume_data=resume_data.get(t_state.torrent_id))
|
||||||
|
deferreds.append(d)
|
||||||
|
|
||||||
self.alerts.wait_on_handler = False
|
deferred_list = DeferredList(deferreds, consumeErrors=False)
|
||||||
log.info("Finished loading %d torrents.", len(state.torrents))
|
|
||||||
component.get("EventManager").emit(SessionStartedEvent())
|
def on_complete(result):
|
||||||
|
log.info("Finished loading %d torrents in %s", len(state.torrents), str(datetime.datetime.now() - start))
|
||||||
|
component.get("EventManager").emit(SessionStartedEvent())
|
||||||
|
deferred_list.addCallback(on_complete)
|
||||||
|
|
||||||
def create_state(self):
|
def create_state(self):
|
||||||
"""Create a state of all the torrents in TorrentManager.
|
"""Create a state of all the torrents in TorrentManager.
|
||||||
|
|
|
@ -32,6 +32,10 @@ class InvalidTorrentError(DelugeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AddTorrentError(DelugeError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class InvalidPathError(DelugeError):
|
class InvalidPathError(DelugeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import os
|
||||||
from hashlib import sha1 as sha
|
from hashlib import sha1 as sha
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from twisted.internet import reactor
|
from twisted.internet import defer, reactor
|
||||||
from twisted.internet.error import CannotListenError
|
from twisted.internet.error import CannotListenError
|
||||||
from twisted.python.failure import Failure
|
from twisted.python.failure import Failure
|
||||||
from twisted.web.http import FORBIDDEN
|
from twisted.web.http import FORBIDDEN
|
||||||
|
@ -16,7 +16,7 @@ import deluge.component as component
|
||||||
import deluge.core.torrent
|
import deluge.core.torrent
|
||||||
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 InvalidTorrentError
|
from deluge.error import AddTorrentError, InvalidTorrentError
|
||||||
from deluge.ui.web.common import compress
|
from deluge.ui.web.common import compress
|
||||||
|
|
||||||
from . import common
|
from . import common
|
||||||
|
@ -102,25 +102,55 @@ class CoreTestCase(BaseTestCase):
|
||||||
|
|
||||||
return component.shutdown().addCallback(on_shutdown)
|
return component.shutdown().addCallback(on_shutdown)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def test_add_torrent_files(self):
|
||||||
|
options = {}
|
||||||
|
filenames = ["test.torrent", "test_torrent.file.torrent"]
|
||||||
|
files_to_add = []
|
||||||
|
for f in filenames:
|
||||||
|
filename = os.path.join(os.path.dirname(__file__), f)
|
||||||
|
filedump = base64.encodestring(open(filename).read())
|
||||||
|
files_to_add.append((filename, filedump, options))
|
||||||
|
errors = yield self.core.add_torrent_files(files_to_add)
|
||||||
|
self.assertEquals(len(errors), 0)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def test_add_torrent_files_error_duplicate(self):
|
||||||
|
options = {}
|
||||||
|
filenames = ["test.torrent", "test.torrent"]
|
||||||
|
files_to_add = []
|
||||||
|
for f in filenames:
|
||||||
|
filename = os.path.join(os.path.dirname(__file__), f)
|
||||||
|
filedump = base64.encodestring(open(filename).read())
|
||||||
|
files_to_add.append((filename, filedump, options))
|
||||||
|
errors = yield self.core.add_torrent_files(files_to_add)
|
||||||
|
self.assertEquals(len(errors), 1)
|
||||||
|
self.assertTrue(str(errors[0]).startswith("Torrent already in session"))
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
def test_add_torrent_file(self):
|
def test_add_torrent_file(self):
|
||||||
options = {}
|
options = {}
|
||||||
filename = os.path.join(os.path.dirname(__file__), "test.torrent")
|
filename = os.path.join(os.path.dirname(__file__), "test.torrent")
|
||||||
torrent_id = self.core.add_torrent_file(filename, base64.encodestring(open(filename).read()), options)
|
torrent_id = yield self.core.add_torrent_file(filename, base64.encodestring(open(filename).read()), options)
|
||||||
|
|
||||||
# Get the info hash from the test.torrent
|
# Get the info hash from the test.torrent
|
||||||
from deluge.bencode import bdecode, bencode
|
from deluge.bencode import bdecode, bencode
|
||||||
info_hash = sha(bencode(bdecode(open(filename).read())["info"])).hexdigest()
|
info_hash = sha(bencode(bdecode(open(filename).read())["info"])).hexdigest()
|
||||||
|
|
||||||
self.assertEquals(torrent_id, info_hash)
|
self.assertEquals(torrent_id, info_hash)
|
||||||
|
|
||||||
|
def test_add_torrent_file_invalid_filedump(self):
|
||||||
|
options = {}
|
||||||
|
filename = os.path.join(os.path.dirname(__file__), "test.torrent")
|
||||||
|
self.assertRaises(AddTorrentError, self.core.add_torrent_file, filename, False, options)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
def test_add_torrent_url(self):
|
def test_add_torrent_url(self):
|
||||||
url = "http://localhost:%d/ubuntu-9.04-desktop-i386.iso.torrent" % self.listen_port
|
url = "http://localhost:%d/ubuntu-9.04-desktop-i386.iso.torrent" % self.listen_port
|
||||||
options = {}
|
options = {}
|
||||||
info_hash = "60d5d82328b4547511fdeac9bf4d0112daa0ce00"
|
info_hash = "60d5d82328b4547511fdeac9bf4d0112daa0ce00"
|
||||||
|
|
||||||
d = self.core.add_torrent_url(url, options)
|
torrent_id = yield self.core.add_torrent_url(url, options)
|
||||||
d.addCallback(self.assertEquals, info_hash)
|
self.assertEquals(torrent_id, info_hash)
|
||||||
return d
|
|
||||||
|
|
||||||
def test_add_torrent_url_with_cookie(self):
|
def test_add_torrent_url_with_cookie(self):
|
||||||
url = "http://localhost:%d/cookie" % self.listen_port
|
url = "http://localhost:%d/cookie" % self.listen_port
|
||||||
|
@ -143,7 +173,6 @@ class CoreTestCase(BaseTestCase):
|
||||||
|
|
||||||
d = self.core.add_torrent_url(url, options)
|
d = self.core.add_torrent_url(url, options)
|
||||||
d.addCallback(self.assertEquals, info_hash)
|
d.addCallback(self.assertEquals, info_hash)
|
||||||
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def test_add_torrent_url_with_partial_download(self):
|
def test_add_torrent_url_with_partial_download(self):
|
||||||
|
@ -153,21 +182,21 @@ class CoreTestCase(BaseTestCase):
|
||||||
|
|
||||||
d = self.core.add_torrent_url(url, options)
|
d = self.core.add_torrent_url(url, options)
|
||||||
d.addCallback(self.assertEquals, info_hash)
|
d.addCallback(self.assertEquals, info_hash)
|
||||||
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def test_add_magnet(self):
|
@defer.inlineCallbacks
|
||||||
|
def test_add_torrent_magnet(self):
|
||||||
info_hash = "60d5d82328b4547511fdeac9bf4d0112daa0ce00"
|
info_hash = "60d5d82328b4547511fdeac9bf4d0112daa0ce00"
|
||||||
uri = deluge.common.create_magnet_uri(info_hash)
|
uri = deluge.common.create_magnet_uri(info_hash)
|
||||||
options = {}
|
options = {}
|
||||||
|
torrent_id = yield self.core.add_torrent_magnet(uri, options)
|
||||||
torrent_id = self.core.add_torrent_magnet(uri, options)
|
|
||||||
self.assertEquals(torrent_id, info_hash)
|
self.assertEquals(torrent_id, info_hash)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
def test_remove_torrent(self):
|
def test_remove_torrent(self):
|
||||||
options = {}
|
options = {}
|
||||||
filename = os.path.join(os.path.dirname(__file__), "test.torrent")
|
filename = os.path.join(os.path.dirname(__file__), "test.torrent")
|
||||||
torrent_id = self.core.add_torrent_file(filename, base64.encodestring(open(filename).read()), options)
|
torrent_id = yield self.core.add_torrent_file(filename, base64.encodestring(open(filename).read()), options)
|
||||||
removed = self.core.remove_torrent(torrent_id, True)
|
removed = self.core.remove_torrent(torrent_id, True)
|
||||||
self.assertTrue(removed)
|
self.assertTrue(removed)
|
||||||
self.assertEquals(len(self.core.get_session_state()), 0)
|
self.assertEquals(len(self.core.get_session_state()), 0)
|
||||||
|
@ -182,12 +211,13 @@ class CoreTestCase(BaseTestCase):
|
||||||
d.addCallback(test_true)
|
d.addCallback(test_true)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
def test_remove_torrents(self):
|
def test_remove_torrents(self):
|
||||||
options = {}
|
options = {}
|
||||||
filename = os.path.join(os.path.dirname(__file__), "test.torrent")
|
filename = os.path.join(os.path.dirname(__file__), "test.torrent")
|
||||||
torrent_id = self.core.add_torrent_file(filename, base64.encodestring(open(filename).read()), options)
|
torrent_id = yield self.core.add_torrent_file(filename, base64.encodestring(open(filename).read()), options)
|
||||||
filename2 = os.path.join(os.path.dirname(__file__), "unicode_filenames.torrent")
|
filename2 = os.path.join(os.path.dirname(__file__), "unicode_filenames.torrent")
|
||||||
torrent_id2 = self.core.add_torrent_file(filename2, base64.encodestring(open(filename2).read()), options)
|
torrent_id2 = yield self.core.add_torrent_file(filename2, base64.encodestring(open(filename2).read()), options)
|
||||||
d = self.core.remove_torrents([torrent_id, torrent_id2], True)
|
d = self.core.remove_torrents([torrent_id, torrent_id2], True)
|
||||||
|
|
||||||
def test_ret(val):
|
def test_ret(val):
|
||||||
|
@ -197,12 +227,13 @@ class CoreTestCase(BaseTestCase):
|
||||||
def test_session_state(val):
|
def test_session_state(val):
|
||||||
self.assertEquals(len(self.core.get_session_state()), 0)
|
self.assertEquals(len(self.core.get_session_state()), 0)
|
||||||
d.addCallback(test_session_state)
|
d.addCallback(test_session_state)
|
||||||
return d
|
yield d
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
def test_remove_torrents_invalid(self):
|
def test_remove_torrents_invalid(self):
|
||||||
options = {}
|
options = {}
|
||||||
filename = os.path.join(os.path.dirname(__file__), "test.torrent")
|
filename = os.path.join(os.path.dirname(__file__), "test.torrent")
|
||||||
torrent_id = self.core.add_torrent_file(filename, base64.encodestring(open(filename).read()), options)
|
torrent_id = yield self.core.add_torrent_file(filename, base64.encodestring(open(filename).read()), options)
|
||||||
d = self.core.remove_torrents(["invalidid1", "invalidid2", torrent_id], False)
|
d = self.core.remove_torrents(["invalidid1", "invalidid2", torrent_id], False)
|
||||||
|
|
||||||
def test_ret(val):
|
def test_ret(val):
|
||||||
|
@ -212,7 +243,7 @@ class CoreTestCase(BaseTestCase):
|
||||||
self.assertTrue(val[1][0] == "invalidid2")
|
self.assertTrue(val[1][0] == "invalidid2")
|
||||||
self.assertTrue(isinstance(val[1][1], InvalidTorrentError))
|
self.assertTrue(isinstance(val[1][1], InvalidTorrentError))
|
||||||
d.addCallback(test_ret)
|
d.addCallback(test_ret)
|
||||||
return d
|
yield d
|
||||||
|
|
||||||
def test_get_session_status(self):
|
def test_get_session_status(self):
|
||||||
status = self.core.get_session_status(["upload_rate", "download_rate"])
|
status = self.core.get_session_status(["upload_rate", "download_rate"])
|
||||||
|
|
|
@ -5,7 +5,7 @@ import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from twisted.internet import reactor
|
from twisted.internet import defer, reactor
|
||||||
from twisted.internet.task import deferLater
|
from twisted.internet.task import deferLater
|
||||||
from twisted.trial import unittest
|
from twisted.trial import unittest
|
||||||
|
|
||||||
|
@ -144,10 +144,11 @@ class TorrentTestCase(unittest.TestCase):
|
||||||
|
|
||||||
# self.print_priority_list(priorities)
|
# self.print_priority_list(priorities)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
def test_torrent_error_data_missing(self):
|
def test_torrent_error_data_missing(self):
|
||||||
options = {"seed_mode": True}
|
options = {"seed_mode": True}
|
||||||
filename = os.path.join(os.path.dirname(__file__), "test_torrent.file.torrent")
|
filename = os.path.join(os.path.dirname(__file__), "test_torrent.file.torrent")
|
||||||
torrent_id = core.add_torrent_file(filename, base64.encodestring(open(filename).read()), options)
|
torrent_id = yield core.add_torrent_file(filename, base64.encodestring(open(filename).read()), options)
|
||||||
torrent = core.torrentmanager.torrents[torrent_id]
|
torrent = core.torrentmanager.torrents[torrent_id]
|
||||||
|
|
||||||
self.assert_state(torrent, "Seeding")
|
self.assert_state(torrent, "Seeding")
|
||||||
|
@ -157,10 +158,11 @@ class TorrentTestCase(unittest.TestCase):
|
||||||
time.sleep(0.2) # Delay to wait for alert from lt
|
time.sleep(0.2) # Delay to wait for alert from lt
|
||||||
self.assert_state(torrent, "Error")
|
self.assert_state(torrent, "Error")
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
def test_torrent_error_resume_original_state(self):
|
def test_torrent_error_resume_original_state(self):
|
||||||
options = {"seed_mode": True, "add_paused": True}
|
options = {"seed_mode": True, "add_paused": True}
|
||||||
filename = os.path.join(os.path.dirname(__file__), "test_torrent.file.torrent")
|
filename = os.path.join(os.path.dirname(__file__), "test_torrent.file.torrent")
|
||||||
torrent_id = core.add_torrent_file(filename, base64.encodestring(open(filename).read()), options)
|
torrent_id = yield core.add_torrent_file(filename, base64.encodestring(open(filename).read()), options)
|
||||||
torrent = core.torrentmanager.torrents[torrent_id]
|
torrent = core.torrentmanager.torrents[torrent_id]
|
||||||
|
|
||||||
orig_state = "Paused"
|
orig_state = "Paused"
|
||||||
|
@ -173,8 +175,10 @@ class TorrentTestCase(unittest.TestCase):
|
||||||
|
|
||||||
# Clear error and verify returned to original state
|
# Clear error and verify returned to original state
|
||||||
torrent.force_recheck()
|
torrent.force_recheck()
|
||||||
return deferLater(reactor, 0.1, self.assert_state, torrent, orig_state)
|
yield deferLater(reactor, 0.1, self.assert_state, torrent, orig_state)
|
||||||
|
return
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
def test_torrent_error_resume_data_unaltered(self):
|
def test_torrent_error_resume_data_unaltered(self):
|
||||||
resume_data = {'active_time': 13399, 'num_incomplete': 16777215, 'announce_to_lsd': 1, 'seed_mode': 0,
|
resume_data = {'active_time': 13399, 'num_incomplete': 16777215, 'announce_to_lsd': 1, 'seed_mode': 0,
|
||||||
'pieces': '\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01', 'paused': 0,
|
'pieces': '\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01', 'paused': 0,
|
||||||
|
@ -202,8 +206,8 @@ class TorrentTestCase(unittest.TestCase):
|
||||||
|
|
||||||
filename = os.path.join(os.path.dirname(__file__), "test_torrent.file.torrent")
|
filename = os.path.join(os.path.dirname(__file__), "test_torrent.file.torrent")
|
||||||
filedump = open(filename).read()
|
filedump = open(filename).read()
|
||||||
torrent_id = core.torrentmanager.add(state=torrent_state, filedump=filedump,
|
torrent_id = yield core.torrentmanager.add(state=torrent_state, filedump=filedump,
|
||||||
resume_data=lt.bencode(resume_data))
|
resume_data=lt.bencode(resume_data))
|
||||||
torrent = core.torrentmanager.torrents[torrent_id]
|
torrent = core.torrentmanager.torrents[torrent_id]
|
||||||
|
|
||||||
def assert_resume_data():
|
def assert_resume_data():
|
||||||
|
@ -211,4 +215,5 @@ class TorrentTestCase(unittest.TestCase):
|
||||||
tm_resume_data = lt.bdecode(core.torrentmanager.resume_data[torrent.torrent_id])
|
tm_resume_data = lt.bdecode(core.torrentmanager.resume_data[torrent.torrent_id])
|
||||||
self.assertEquals(tm_resume_data, resume_data)
|
self.assertEquals(tm_resume_data, resume_data)
|
||||||
|
|
||||||
return deferLater(reactor, 0.5, assert_resume_data)
|
yield deferLater(reactor, 0.5, assert_resume_data)
|
||||||
|
return
|
||||||
|
|
|
@ -2,6 +2,7 @@ import base64
|
||||||
import os
|
import os
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
from twisted.internet import defer
|
||||||
from twisted.trial import unittest
|
from twisted.trial import unittest
|
||||||
|
|
||||||
from deluge import component
|
from deluge import component
|
||||||
|
@ -32,9 +33,10 @@ class TorrentmanagerTestCase(unittest.TestCase):
|
||||||
del self.torrentManager
|
del self.torrentManager
|
||||||
return component.shutdown().addCallback(on_shutdown)
|
return component.shutdown().addCallback(on_shutdown)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
def test_remove_torrent(self):
|
def test_remove_torrent(self):
|
||||||
filename = os.path.join(os.path.dirname(__file__), "test.torrent")
|
filename = os.path.join(os.path.dirname(__file__), "test.torrent")
|
||||||
torrent_id = self.core.add_torrent_file(filename, base64.encodestring(open(filename).read()), {})
|
torrent_id = yield self.core.add_torrent_file(filename, base64.encodestring(open(filename).read()), {})
|
||||||
self.assertTrue(self.torrentManager.remove(torrent_id, False))
|
self.assertTrue(self.torrentManager.remove(torrent_id, False))
|
||||||
|
|
||||||
def test_remove_torrent_false(self):
|
def test_remove_torrent_false(self):
|
||||||
|
|
|
@ -738,8 +738,13 @@ class AddTorrentDialog(component.Component):
|
||||||
options))
|
options))
|
||||||
row = self.torrent_liststore.iter_next(row)
|
row = self.torrent_liststore.iter_next(row)
|
||||||
|
|
||||||
def on_torrents_added(torrent_ids):
|
def on_torrents_added(errors):
|
||||||
log.info("Added %d torrents", len(torrent_ids))
|
if errors:
|
||||||
|
log.info("Failed to add %d out of %d torrents.", len(errors), len(torrents_to_add))
|
||||||
|
for e in errors:
|
||||||
|
log.info("Torrent add failed: %s", e)
|
||||||
|
else:
|
||||||
|
log.info("Successfully added %d torrents.", len(torrents_to_add))
|
||||||
client.core.add_torrent_files(torrents_to_add).addCallback(on_torrents_added)
|
client.core.add_torrent_files(torrents_to_add).addCallback(on_torrents_added)
|
||||||
|
|
||||||
def _on_button_apply_clicked(self, widget):
|
def _on_button_apply_clicked(self, widget):
|
||||||
|
|
Loading…
Reference in New Issue