[#3126|Core] Restore synchonous add torrent methods for backward compatibilty

The synchonous add torrent method was replaced with async but this
break backward compatibility with 3rd party plugins and clients.

Added a new add_torrent_file_async method for adding single torrent.

Torrent manager has a new add_async method and split up code to prevent
duplication.

Update any use of add_torrent_file to add_torrent_file_async. Future
refactoring could use add_torrent_files instead.
This commit is contained in:
Calum Lind 2017-11-18 15:05:02 +00:00
commit 2644169376
11 changed files with 267 additions and 159 deletions

View file

@ -10,13 +10,13 @@
from __future__ import division, unicode_literals from __future__ import division, unicode_literals
import base64
import glob import glob
import logging import logging
import os import os
import shutil import shutil
import tempfile import tempfile
import threading import threading
from base64 import b64decode, b64encode
from twisted.internet import defer, reactor, task from twisted.internet import defer, reactor, task
from twisted.web.client import getPage from twisted.web.client import getPage
@ -317,8 +317,10 @@ class Core(component.Component):
return self.new_release return self.new_release
return False return False
def _add_torrent_file(self, filename, filedump, options, save_state=True): # Exported Methods
"""Adds a torrent file to the session. @export
def add_torrent_file_async(self, filename, filedump, options, save_state=True):
"""Adds a torrent file to the session asynchonously.
Args: Args:
filename (str): The filename of the torrent. filename (str): The filename of the torrent.
@ -327,16 +329,16 @@ class Core(component.Component):
save_state (bool): If the state should be saved after adding the file. save_state (bool): If the state should be saved after adding the file.
Returns: Returns:
str: The torrent ID or None. Deferred: The torrent ID or None.
""" """
try: try:
filedump = base64.decodestring(filedump) filedump = b64decode(filedump)
except Exception as ex: except Exception as ex:
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:
d = self.torrentmanager.add( d = self.torrentmanager.add_async(
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:
@ -345,7 +347,6 @@ class Core(component.Component):
else: else:
return d return d
# Exported Methods
@export @export
def add_torrent_file(self, filename, filedump, options): def add_torrent_file(self, filename, filedump, options):
"""Adds a torrent file to the session. """Adds a torrent file to the session.
@ -359,11 +360,21 @@ class Core(component.Component):
str: The torrent_id or None. str: The torrent_id or None.
""" """
return self._add_torrent_file(filename, filedump, options) try:
filedump = b64decode(filedump)
except Exception as ex:
log.error('There was an error decoding the filedump string: %s', ex)
try:
return self.torrentmanager.add(
filedump=filedump, options=options, filename=filename)
except RuntimeError as ex:
log.error('There was an error adding the torrent file %s: %s', filename, ex)
raise
@export @export
def add_torrent_files(self, torrent_files): def add_torrent_files(self, torrent_files):
"""Adds multiple torrent files to the session. """Adds multiple torrent files to the session asynchonously.
Args: Args:
torrent_files (list of tuples): Torrent files as tuple of (filename, filedump, options). torrent_files (list of tuples): Torrent files as tuple of (filename, filedump, options).
@ -378,8 +389,8 @@ class Core(component.Component):
last_index = len(torrent_files) - 1 last_index = len(torrent_files) - 1
for idx, torrent in enumerate(torrent_files): for idx, torrent in enumerate(torrent_files):
try: try:
yield self._add_torrent_file(torrent[0], torrent[1], yield self.add_torrent_file_async(
torrent[2], save_state=idx == last_index) torrent[0], torrent[1], torrent[2], save_state=idx == last_index)
except AddTorrentError as ex: except AddTorrentError as ex:
log.warn('Error when adding torrent: %s', ex) log.warn('Error when adding torrent: %s', ex)
errors.append(ex) errors.append(ex)
@ -411,7 +422,7 @@ class Core(component.Component):
os.remove(filename) os.remove(filename)
except OSError as ex: except OSError as ex:
log.warning('Could not remove temp file: %s', ex) log.warning('Could not remove temp file: %s', ex)
return self.add_torrent_file(filename, base64.encodestring(data), options) return self.add_torrent_file(filename, b64encode(data), options)
def on_download_fail(failure): def on_download_fail(failure):
# Log the error and pass the failure onto the client # Log the error and pass the failure onto the client
@ -843,7 +854,7 @@ class Core(component.Component):
options = {} options = {}
options['download_location'] = os.path.split(path)[0] options['download_location'] = os.path.split(path)[0]
with open(target, 'rb') as _file: with open(target, 'rb') as _file:
filedump = base64.encodestring(_file.read()) filedump = b64encode(_file.read())
self.add_torrent_file(os.path.split(target)[1], filedump, options) self.add_torrent_file(os.path.split(target)[1], filedump, options)
@export @export
@ -854,7 +865,7 @@ class Core(component.Component):
ie, plugin_file.read()""" ie, plugin_file.read()"""
try: try:
filedump = base64.decodestring(filedump) filedump = b64decode(filedump)
except Exception as ex: except Exception as ex:
log.error('There was an error decoding the filedump string!') log.error('There was an error decoding the filedump string!')
log.exception(ex) log.exception(ex)

View file

@ -293,8 +293,94 @@ class TorrentManager(component.Component):
else: else:
return torrent_info return torrent_info
def add(self, torrent_info=None, state=None, options=None, save_state=True, def _build_torrent_options(self, options):
filedump=None, filename=None, magnet=None, resume_data=None): """Load default options and update if needed."""
_options = TorrentOptions()
if options:
_options.update(options)
options = _options
if not options['owner']:
options['owner'] = component.get('RPCServer').get_session_user()
if not component.get('AuthManager').has_account(options['owner']):
options['owner'] = 'localclient'
return options
def _build_torrent_params(
self, torrent_info=None, magnet=None, options=None, resume_data=None
):
"""Create the add_torrent_params dict for adding torrent to libtorrent."""
add_torrent_params = {}
if torrent_info:
add_torrent_params['ti'] = torrent_info
name = torrent_info.name()
if not name:
name = torrent_info.file_at(0).path.replace('\\', '/', 1).split('/', 1)[0]
add_torrent_params['name'] = name
torrent_id = str(torrent_info.info_hash())
elif magnet:
magnet_info = get_magnet_info(magnet)
if magnet_info:
add_torrent_params['url'] = magnet.strip().encode('utf8')
add_torrent_params['name'] = magnet_info['name']
torrent_id = magnet_info['info_hash']
else:
raise AddTorrentError('Unable to add magnet, invalid magnet info: %s' % magnet)
# Check for existing torrent in session.
if torrent_id in self.get_torrent_list():
# Attempt merge trackers before returning.
self.torrents[torrent_id].merge_trackers(torrent_info)
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)
# Check for renamed files and if so, rename them in the torrent_info before adding.
if options['mapped_files'] and torrent_info:
for index, fname in options['mapped_files'].items():
fname = sanitize_filepath(decode_bytes(fname))
if log.isEnabledFor(logging.DEBUG):
log.debug('renaming file index %s to %s', index, fname)
try:
torrent_info.rename_file(index, fname.encode('utf8'))
except TypeError:
torrent_info.rename_file(index, fname)
add_torrent_params['ti'] = torrent_info
if log.isEnabledFor(logging.DEBUG):
log.debug('options: %s', options)
# Fill in the rest of the add_torrent_params dictionary.
add_torrent_params['save_path'] = options['download_location'].encode('utf8')
if options['name']:
add_torrent_params['name'] = options['name']
if options['pre_allocate_storage']:
add_torrent_params['storage_mode'] = lt.storage_mode_t.storage_mode_allocate
if resume_data:
add_torrent_params['resume_data'] = resume_data
# Set flags: enable duplicate_is_error & override_resume_data, disable auto_managed.
add_torrent_params['flags'] = ((LT_DEFAULT_ADD_TORRENT_FLAGS |
lt.add_torrent_params_flags_t.flag_duplicate_is_error |
lt.add_torrent_params_flags_t.flag_override_resume_data) ^
lt.add_torrent_params_flags_t.flag_auto_managed)
if options['seed_mode']:
add_torrent_params['flags'] |= lt.add_torrent_params_flags_t.flag_seed_mode
return torrent_id, add_torrent_params
def add(
self,
torrent_info=None,
state=None,
options=None,
save_state=True,
filedump=None,
filename=None,
magnet=None,
resume_data=None,
):
"""Adds a torrent to the torrent manager. """Adds a torrent to the torrent manager.
Args: Args:
@ -323,73 +409,68 @@ class TorrentManager(component.Component):
except RuntimeError as ex: except RuntimeError as ex:
raise AddTorrentError('Unable to add torrent, decoding filedump failed: %s' % ex) raise AddTorrentError('Unable to add torrent, decoding filedump failed: %s' % ex)
add_torrent_params = {} options = self._build_torrent_options(options)
if torrent_info: __, add_torrent_params = self._build_torrent_params(
add_torrent_params['ti'] = torrent_info torrent_info, magnet, options, resume_data)
name = torrent_info.name()
if not name:
name = torrent_info.file_at(0).path.replace('\\', '/', 1).split('/', 1)[0]
add_torrent_params['name'] = name
torrent_id = str(torrent_info.info_hash())
elif magnet:
magnet_info = get_magnet_info(magnet)
if magnet_info:
add_torrent_params['url'] = magnet.strip().encode('utf8')
add_torrent_params['name'] = magnet_info['name']
torrent_id = magnet_info['info_hash']
else:
raise AddTorrentError('Unable to add magnet, invalid magnet info: %s' % magnet)
# Check for existing torrent in session. # We need to pause the AlertManager momentarily to prevent alerts
if torrent_id in self.get_torrent_list(): # for this torrent being generated before a Torrent object is created.
# Attempt merge trackers before returning. component.pause('AlertManager')
self.torrents[torrent_id].merge_trackers(torrent_info)
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. try:
_options = TorrentOptions() handle = self.session.add_torrent(add_torrent_params)
if options: if not handle.is_valid():
_options.update(options) raise InvalidTorrentError('Torrent handle is invalid!')
options = _options except (RuntimeError, InvalidTorrentError) as ex:
component.resume('AlertManager')
raise AddTorrentError('Unable to add torrent to session: %s' % ex)
# Check for renamed files and if so, rename them in the torrent_info before adding. torrent = self._add_torrent_obj(
if options['mapped_files'] and torrent_info: handle, options, state, filename, magnet, resume_data, filedump, save_state)
for index, fname in options['mapped_files'].items(): return torrent.torrent_id
fname = sanitize_filepath(decode_bytes(fname))
if log.isEnabledFor(logging.DEBUG):
log.debug('renaming file index %s to %s', index, fname)
try:
torrent_info.rename_file(index, fname.encode('utf8'))
except TypeError:
torrent_info.rename_file(index, fname)
add_torrent_params['ti'] = torrent_info
if not options['owner']: def add_async(
options['owner'] = component.get('RPCServer').get_session_user() self,
if not component.get('AuthManager').has_account(options['owner']): torrent_info=None,
options['owner'] = 'localclient' state=None,
options=None,
save_state=True,
filedump=None,
filename=None,
magnet=None,
resume_data=None,
):
"""Adds a torrent to the torrent manager using libtorrent async add torrent method.
if log.isEnabledFor(logging.DEBUG): Args:
log.debug('options: %s', options) torrent_info (lt.torrent_info, optional): A libtorrent torrent_info object.
state (TorrentState, optional): The torrent state.
options (dict, optional): The options to apply to the torrent on adding.
save_state (bool, optional): If True save the session state after adding torrent, defaults to True.
filedump (str, optional): bencoded filedump of a torrent file.
filename (str, optional): The filename of the torrent file.
magnet (str, optional): The magnet uri.
resume_data (lt.entry, optional): libtorrent fast resume data.
# Fill in the rest of the add_torrent_params dictionary. Returns:
add_torrent_params['save_path'] = options['download_location'].encode('utf8') Deferred: If successful the torrent_id of the added torrent, None if adding the torrent failed.
if options['name']:
add_torrent_params['name'] = options['name']
if options['pre_allocate_storage']:
add_torrent_params['storage_mode'] = lt.storage_mode_t.storage_mode_allocate
if resume_data:
add_torrent_params['resume_data'] = resume_data
# Set flags: enable duplicate_is_error & override_resume_data, disable auto_managed. Emits:
add_torrent_params['flags'] = ((LT_DEFAULT_ADD_TORRENT_FLAGS | TorrentAddedEvent: Torrent with torrent_id added to session.
lt.add_torrent_params_flags_t.flag_duplicate_is_error |
lt.add_torrent_params_flags_t.flag_override_resume_data) ^ """
lt.add_torrent_params_flags_t.flag_auto_managed) if not torrent_info and not filedump and not magnet:
if options['seed_mode']: raise AddTorrentError('You must specify a valid torrent_info, torrent state or magnet.')
add_torrent_params['flags'] |= lt.add_torrent_params_flags_t.flag_seed_mode
if filedump:
try:
torrent_info = lt.torrent_info(lt.bdecode(filedump))
except RuntimeError as ex:
raise AddTorrentError('Unable to add torrent, decoding filedump failed: %s' % ex)
options = self._build_torrent_options(options)
torrent_id, add_torrent_params = self._build_torrent_params(
torrent_info, magnet, options, resume_data)
d = Deferred() d = Deferred()
self.torrents_loading[torrent_id] = (d, options, state, filename, magnet, resume_data, filedump, save_state) self.torrents_loading[torrent_id] = (d, options, state, filename, magnet, resume_data, filedump, save_state)
@ -399,6 +480,58 @@ class TorrentManager(component.Component):
raise AddTorrentError('Unable to add torrent to session: %s' % ex) raise AddTorrentError('Unable to add torrent to session: %s' % ex)
return d return d
def _add_torrent_obj(self, handle, options, state, filename, magnet, resume_data, filedump, save_state):
# Create a Torrent object and add to the dictionary.
torrent = Torrent(handle, options, state, filename, magnet)
self.torrents[torrent.torrent_id] = torrent
# Resume AlertManager if paused for adding torrent to libtorrent.
component.resume('AlertManager')
# Store the orignal resume_data, in case of errors.
if resume_data:
self.resume_data[torrent.torrent_id] = resume_data
# Add to queued torrents set.
self.queued_torrents.add(torrent.torrent_id)
if self.config['queue_new_to_top']:
self.queue_top(torrent.torrent_id)
# Resume the torrent if needed.
if not options['add_paused']:
torrent.resume()
# Emit torrent_added signal.
from_state = state is not None
component.get('EventManager').emit(TorrentAddedEvent(torrent.torrent_id, from_state))
if log.isEnabledFor(logging.DEBUG):
log.debug('Torrent added: %s', str(handle.info_hash()))
if log.isEnabledFor(logging.INFO):
name_and_owner = torrent.get_status(['name', 'owner'])
log.info('Torrent %s from user "%s" %s',
name_and_owner['name'],
name_and_owner['owner'],
from_state and 'loaded' or 'added')
# Write the .torrent file to the state directory.
if filedump:
torrent.write_torrentfile(filedump)
# Save the session state.
if save_state:
self.save_state()
return torrent
def add_async_callback(
self, handle, d, options, state, filename, magnet, resume_data, filedump, save_state
):
torrent = self._add_torrent_obj(
handle, options, state, filename, magnet, resume_data, filedump, save_state)
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.
@ -898,51 +1031,12 @@ class TorrentManager(component.Component):
return return
try: try:
(d, options, state, filename, magnet, resume_data, filedump, add_async_params = self.torrents_loading.pop(torrent_id)
save_state) = self.torrents_loading.pop(torrent_id)
except KeyError as ex: except KeyError as ex:
log.warn('Torrent id not in torrents loading list: %s', ex) log.warn('Torrent id not in torrents loading list: %s', ex)
return return
# Create a Torrent object and add to the dictionary. self.add_async_callback(alert.handle, *add_async_params)
torrent = Torrent(alert.handle, options, state, filename, magnet)
self.torrents[torrent.torrent_id] = torrent
# Store the orignal resume_data, in case of errors.
if resume_data:
self.resume_data[torrent.torrent_id] = resume_data
# Add to queued torrents set.
self.queued_torrents.add(torrent.torrent_id)
if self.config['queue_new_to_top']:
self.queue_top(torrent.torrent_id)
# Resume the torrent if needed.
if not options['add_paused']:
torrent.resume()
# Emit torrent_added signal.
from_state = state is not None
component.get('EventManager').emit(TorrentAddedEvent(torrent.torrent_id, from_state))
if log.isEnabledFor(logging.DEBUG):
log.debug('Torrent added: %s', str(alert.handle.info_hash()))
if log.isEnabledFor(logging.INFO):
name_and_owner = torrent.get_status(['name', 'owner'])
log.info('Torrent %s from user "%s" %s',
name_and_owner['name'],
name_and_owner['owner'],
from_state and 'loaded' or 'added')
# Write the .torrent file to the state directory.
if filedump:
torrent.write_torrentfile(filedump)
# Save the session state.
if save_state:
self.save_state()
d.callback(torrent.torrent_id)
def on_alert_torrent_finished(self, alert): def on_alert_torrent_finished(self, alert):
"""Alert handler for libtorrent torrent_finished_alert""" """Alert handler for libtorrent torrent_finished_alert"""

View file

@ -321,7 +321,7 @@ class Core(CorePluginBase):
if magnet: if magnet:
d = component.get('Core').add_torrent_magnet(filedump.strip(), options) d = component.get('Core').add_torrent_magnet(filedump.strip(), options)
else: else:
d = component.get('Core').add_torrent_file( d = component.get('Core').add_torrent_file_async(
filename, base64.encodestring(filedump), options) filename, base64.encodestring(filedump), options)
d.addCallback(on_torrent_added, filename, filepath) d.addCallback(on_torrent_added, filename, filepath)
d.addErrback(fail_torrent_add, filepath, magnet) d.addErrback(fail_torrent_add, filepath, magnet)

View file

@ -145,7 +145,7 @@ class CoreTestCase(BaseTestCase):
filename = common.get_test_data_file('test.torrent') filename = common.get_test_data_file('test.torrent')
with open(filename, 'rb') as _file: with open(filename, 'rb') as _file:
filedump = base64.encodestring(_file.read()) filedump = base64.encodestring(_file.read())
torrent_id = yield self.core.add_torrent_file(filename, filedump, options) torrent_id = yield self.core.add_torrent_file_async(filename, filedump, 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
@ -213,7 +213,7 @@ class CoreTestCase(BaseTestCase):
filename = common.get_test_data_file('test.torrent') filename = common.get_test_data_file('test.torrent')
with open(filename, 'rb') as _file: with open(filename, 'rb') as _file:
filedump = base64.encodestring(_file.read()) filedump = base64.encodestring(_file.read())
torrent_id = yield self.core.add_torrent_file(filename, filedump, options) torrent_id = yield self.core.add_torrent_file_async(filename, filedump, options)
removed = self.core.remove_torrent(torrent_id, True) removed = self.core.remove_torrent(torrent_id, True)
self.assertTrue(removed) self.assertTrue(removed)
self.assertEqual(len(self.core.get_session_state()), 0) self.assertEqual(len(self.core.get_session_state()), 0)
@ -227,12 +227,12 @@ class CoreTestCase(BaseTestCase):
filename = common.get_test_data_file('test.torrent') filename = common.get_test_data_file('test.torrent')
with open(filename, 'rb') as _file: with open(filename, 'rb') as _file:
filedump = base64.encodestring(_file.read()) filedump = base64.encodestring(_file.read())
torrent_id = yield self.core.add_torrent_file(filename, filedump, options) torrent_id = yield self.core.add_torrent_file_async(filename, filedump, options)
filename2 = common.get_test_data_file('unicode_filenames.torrent') filename2 = common.get_test_data_file('unicode_filenames.torrent')
with open(filename2, 'rb') as _file: with open(filename2, 'rb') as _file:
filedump = base64.encodestring(_file.read()) filedump = base64.encodestring(_file.read())
torrent_id2 = yield self.core.add_torrent_file(filename2, filedump, options) torrent_id2 = yield self.core.add_torrent_file_async(filename2, filedump, 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):
@ -250,7 +250,7 @@ class CoreTestCase(BaseTestCase):
filename = common.get_test_data_file('test.torrent') filename = common.get_test_data_file('test.torrent')
with open(filename, 'rb') as _file: with open(filename, 'rb') as _file:
filedump = base64.encodestring(_file.read()) filedump = base64.encodestring(_file.read())
torrent_id = yield self.core.add_torrent_file(filename, filedump, options) torrent_id = yield self.core.add_torrent_file_async(filename, filedump, options)
val = yield self.core.remove_torrents(['invalidid1', 'invalidid2', torrent_id], False) val = yield self.core.remove_torrents(['invalidid1', 'invalidid2', torrent_id], False)
self.assertEqual(len(val), 2) self.assertEqual(len(val), 2)
self.assertEqual(val[0], ('invalidid1', 'torrent_id invalidid1 not in session.')) self.assertEqual(val[0], ('invalidid1', 'torrent_id invalidid1 not in session.'))

View file

@ -11,7 +11,7 @@ import base64
import os import os
import time import time
from twisted.internet import defer, reactor from twisted.internet import reactor
from twisted.internet.task import deferLater from twisted.internet.task import deferLater
import deluge.component as component import deluge.component as component
@ -113,13 +113,12 @@ class TorrentTestCase(BaseTestCase):
# 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 = common.get_test_data_file('test_torrent.file.torrent') filename = common.get_test_data_file('test_torrent.file.torrent')
with open(filename) as _file: with open(filename) as _file:
filedump = base64.encodestring(_file.read()) filedump = base64.encodestring(_file.read())
torrent_id = yield self.core.add_torrent_file(filename, filedump, options) torrent_id = self.core.add_torrent_file(filename, filedump, options)
torrent = self.core.torrentmanager.torrents[torrent_id] torrent = self.core.torrentmanager.torrents[torrent_id]
self.assert_state(torrent, 'Seeding') self.assert_state(torrent, 'Seeding')
@ -129,13 +128,12 @@ class TorrentTestCase(BaseTestCase):
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 = common.get_test_data_file('test_torrent.file.torrent') filename = common.get_test_data_file('test_torrent.file.torrent')
with open(filename) as _file: with open(filename) as _file:
filedump = base64.encodestring(_file.read()) filedump = base64.encodestring(_file.read())
torrent_id = yield self.core.add_torrent_file(filename, filedump, options) torrent_id = self.core.add_torrent_file(filename, filedump, options)
torrent = self.core.torrentmanager.torrents[torrent_id] torrent = self.core.torrentmanager.torrents[torrent_id]
orig_state = 'Paused' orig_state = 'Paused'
@ -148,26 +146,25 @@ class TorrentTestCase(BaseTestCase):
# Clear error and verify returned to original state # Clear error and verify returned to original state
torrent.force_recheck() torrent.force_recheck()
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 = {
'pieces': '\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01', 'paused': 0, 'active_time': 13399, 'num_incomplete': 16777215, 'announce_to_lsd': 1, 'seed_mode': 0,
'seeding_time': 13399, 'last_scrape': 13399, 'pieces': '\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01', 'paused': 0,
'info-hash': '-\xc5\xd0\xe7\x1af\xfeid\x9ad\r9\xcb\x00\xa2YpIs', 'max_uploads': 16777215, 'seeding_time': 13399, 'last_scrape': 13399,
'max_connections': 16777215, 'num_downloaders': 16777215, 'total_downloaded': 0, 'info-hash': '-\xc5\xd0\xe7\x1af\xfeid\x9ad\r9\xcb\x00\xa2YpIs', 'max_uploads': 16777215,
'file-format': 'libtorrent resume file', 'peers6': '', 'added_time': 1411826665, 'max_connections': 16777215, 'num_downloaders': 16777215, 'total_downloaded': 0,
'banned_peers6': '', 'file_priority': [1], 'last_seen_complete': 0, 'total_uploaded': 0, 'file-format': 'libtorrent resume file', 'peers6': '', 'added_time': 1411826665,
'piece_priority': '\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01', 'banned_peers6': '', 'file_priority': [1], 'last_seen_complete': 0, 'total_uploaded': 0,
'file-version': 1, 'announce_to_dht': 1, 'auto_managed': 1, 'upload_rate_limit': 0, 'piece_priority': '\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01',
'completed_time': 1411826665, 'allocation': 'sparse', 'blocks per piece': 2, 'file-version': 1, 'announce_to_dht': 1, 'auto_managed': 1, 'upload_rate_limit': 0,
'download_rate_limit': 0, 'libtorrent-version': '0.16.17.0', 'banned_peers': '', 'completed_time': 1411826665, 'allocation': 'sparse', 'blocks per piece': 2,
'num_seeds': 16777215, 'sequential_download': 0, 'announce_to_trackers': 1, 'download_rate_limit': 0, 'libtorrent-version': '0.16.17.0', 'banned_peers': '',
'peers': '\n\x00\x02\x0f=\xc6SC\x17]\xd8}\x7f\x00\x00\x01=\xc6', 'finished_time': 13399, 'num_seeds': 16777215, 'sequential_download': 0, 'announce_to_trackers': 1,
'last_upload': 13399, 'trackers': [[]], 'super_seeding': 0, 'peers': '\n\x00\x02\x0f=\xc6SC\x17]\xd8}\x7f\x00\x00\x01=\xc6', 'finished_time': 13399,
'file sizes': [[512000, 1411826586]], 'last_download': 13399} 'last_upload': 13399, 'trackers': [[]], 'super_seeding': 0,
'file sizes': [[512000, 1411826586]], 'last_download': 13399
}
torrent_state = TorrentState( torrent_state = TorrentState(
torrent_id='2dc5d0e71a66fe69649a640d39cb00a259704973', torrent_id='2dc5d0e71a66fe69649a640d39cb00a259704973',
filename='test_torrent.file.torrent', filename='test_torrent.file.torrent',
@ -181,8 +178,8 @@ class TorrentTestCase(BaseTestCase):
with open(filename) as _file: with open(filename) as _file:
filedump = _file.read() filedump = _file.read()
resume_data = utf8_encode_structure(resume_data) resume_data = utf8_encode_structure(resume_data)
torrent_id = yield self.core.torrentmanager.add(state=torrent_state, filedump=filedump, torrent_id = self.core.torrentmanager.add(
resume_data=lt.bencode(resume_data)) state=torrent_state, filedump=filedump, resume_data=lt.bencode(resume_data))
torrent = self.core.torrentmanager.torrents[torrent_id] torrent = self.core.torrentmanager.torrents[torrent_id]
def assert_resume_data(): def assert_resume_data():
@ -190,5 +187,4 @@ class TorrentTestCase(BaseTestCase):
tm_resume_data = lt.bdecode(self.core.torrentmanager.resume_data[torrent.torrent_id]) tm_resume_data = lt.bdecode(self.core.torrentmanager.resume_data[torrent.torrent_id])
self.assertEqual(tm_resume_data, resume_data) self.assertEqual(tm_resume_data, resume_data)
yield deferLater(reactor, 0.5, assert_resume_data) return deferLater(reactor, 0.5, assert_resume_data)
return

View file

@ -41,7 +41,7 @@ class TorrentmanagerTestCase(BaseTestCase):
filename = common.get_test_data_file('test.torrent') filename = common.get_test_data_file('test.torrent')
with open(filename) as _file: with open(filename) as _file:
filedump = base64.encodestring(_file.read()) filedump = base64.encodestring(_file.read())
torrent_id = yield self.core.add_torrent_file(filename, filedump, {}) torrent_id = yield self.core.add_torrent_file_async(filename, filedump, {})
self.assertTrue(self.core.torrentmanager.remove(torrent_id, False)) self.assertTrue(self.core.torrentmanager.remove(torrent_id, False))
@pytest.mark.todo @pytest.mark.todo

View file

@ -82,8 +82,11 @@ class Command(BaseCommand):
filename = os.path.split(path)[-1] filename = os.path.split(path)[-1]
with open(path, 'rb') as _file: with open(path, 'rb') as _file:
filedump = base64.encodestring(_file.read()) filedump = base64.encodestring(_file.read())
deferreds.append(client.core.add_torrent_file(filename, filedump, t_options).addCallback( deferreds.append(
on_success).addErrback(on_fail)) client.core.add_torrent_file_async(
filename, filedump, t_options,
).addCallback(on_success).addErrback(on_fail)
)
return defer.DeferredList(deferreds) return defer.DeferredList(deferreds)

View file

@ -80,5 +80,6 @@ def add_torrent(t_file, options, success_cb, fail_cb, ress):
with open(f, 'rb') as _file: with open(f, 'rb') as _file:
filedump = base64.encodestring(_file.read()) filedump = base64.encodestring(_file.read())
client.core.add_torrent_file( client.core.add_torrent_file_async(
filename, filedump, t_options).addCallback(success_cb, f, ress).addErrback(fail_cb, f, ress) filename, filedump, t_options
).addCallback(success_cb, f, ress).addErrback(fail_cb, f, ress)

View file

@ -399,7 +399,7 @@ class AddTorrents(BaseMode):
t_options['download_location'] = result['location']['value'] t_options['download_location'] = result['location']['value']
t_options['add_paused'] = result['add_paused']['value'] t_options['add_paused'] = result['add_paused']['value']
d = client.core.add_torrent_file(filename, filedump, t_options) d = client.core.add_torrent_file_async(filename, filedump, t_options)
d.addCallback(success_cb, filename, ress) d.addCallback(success_cb, filename, ress)
d.addErrback(fail_cb, filename, ress) d.addErrback(fail_cb, filename, ress)

View file

@ -366,8 +366,11 @@ class CreateTorrentDialog(object):
if add_to_session: if add_to_session:
with open(target, 'rb') as _file: with open(target, 'rb') as _file:
filedump = base64.encodestring(_file.read()) filedump = base64.encodestring(_file.read())
client.core.add_torrent_file(os.path.split(target)[-1], filedump, client.core.add_torrent_file_async(
{'download_location': os.path.split(path)[0]}) os.path.split(target)[-1],
filedump,
{'download_location': os.path.split(path)[0]}
)
def _on_create_torrent_progress(self, value, num_pieces): def _on_create_torrent_progress(self, value, num_pieces):
percent = value / num_pieces percent = value / num_pieces

View file

@ -677,7 +677,7 @@ class WebApi(JSONComponent):
fdump = base64.encodestring(_file.read()) fdump = base64.encodestring(_file.read())
log.info('Adding torrent from file `%s` with options `%r`', log.info('Adding torrent from file `%s` with options `%r`',
filename, torrent['options']) filename, torrent['options'])
d = client.core.add_torrent_file(filename, fdump, torrent['options']) d = client.core.add_torrent_file_async(filename, fdump, torrent['options'])
deferreds.append(d) deferreds.append(d)
return DeferredList(deferreds, consumeErrors=False) return DeferredList(deferreds, consumeErrors=False)