Downloader options in its own class, show options in gui downloader

Put stream downloader options into its own class, and make stream
downloader options global to the stream type rather than specific
to each factory.

Show downloader options in the lbrynet-downloader-gui.

Make a class for downloader option choices, so that the descriptions
can be displayed.

In the console, if there are multiple choices for the download
option, make it a list selected by its index.

Make sure that the ConnectionManager closes properly when some of
the connections fail to open (e.g. due to a host being down)
This commit is contained in:
Jimmy Kiselak 2015-08-27 15:41:17 -04:00
parent f4b3187494
commit c8b2b7b279
18 changed files with 583 additions and 231 deletions

View file

@ -1,6 +1,16 @@
class DownloadChoice(object):
def __init__(self, value, short_description, long_description, bool_options_description=None):
self.value = value
self.short_description = short_description
self.long_description = long_description
self.bool_options_description = bool_options_description
class DownloadOption(object):
def __init__(self, option_types, long_description, short_description, default):
def __init__(self, option_types, long_description, short_description, default_value,
default_value_description):
self.option_types = option_types
self.long_description = long_description
self.short_description = short_description
self.default = default
self.default_value = default_value
self.default_value_description = default_value_description

View file

@ -110,9 +110,10 @@ class StreamDescriptorIdentifier(object):
"""
def __init__(self):
self._sd_info_validators = {} # {stream_type: IStreamDescriptorValidator}
self._stream_options = {} # {stream_type: IStreamOptions}
self._stream_downloader_factories = defaultdict(list) # {stream_type: [IStreamDownloaderFactory]}
def add_stream_info_validator(self, stream_type, sd_info_validator):
def add_stream_type(self, stream_type, sd_info_validator, stream_options):
"""
This is how the StreamDescriptorIdentifier learns about new types of stream descriptors.
@ -126,9 +127,13 @@ class StreamDescriptorIdentifier(object):
will then be called. If the validation step fails, an exception will be thrown, preventing the stream
descriptor from being further processed.
@param stream_options: A class implementing the IStreamOptions interface. This class's constructor will be
passed the sd_info_validator object containing the raw metadata from the stream descriptor file.
@return: None
"""
self._sd_info_validators[stream_type] = sd_info_validator
self._stream_options[stream_type] = stream_options
def add_stream_downloader_factory(self, stream_type, factory):
"""
@ -167,14 +172,23 @@ class StreamDescriptorIdentifier(object):
assert stream_type in self._sd_info_validators, "Unrecognized stream type: " + str(stream_type)
return self._sd_info_validators[stream_type]
def _get_options(self, stream_type):
assert stream_type in self._sd_info_validators, "Unrecognized stream type: " + str(stream_type)
return self._stream_options[stream_type]
def _return_info_and_factories(self, sd_info):
assert 'stream_type' in sd_info, 'Invalid stream descriptor. No stream_type parameter.'
stream_type = sd_info['stream_type']
factories = self._get_factories(stream_type)
validator = self._get_validator(stream_type)(sd_info)
factories = [f for f in self._get_factories(stream_type) if f.can_download(validator)]
d = validator.validate()
d.addCallback(lambda _: (validator, factories))
def get_options():
options = self._get_options(stream_type)
return validator, options, factories
d.addCallback(lambda _: get_options())
return d

View file

@ -7,49 +7,55 @@ from lbrynet.core.client.ClientProtocol import ClientProtocolFactory
from lbrynet.core.Error import InsufficientFundsError
class PeerConnectionHandler(object):
def __init__(self, request_creators, factory):
self.request_creators = request_creators
self.factory = factory
self.connection = None
class ConnectionManager(object):
implements(interfaces.IConnectionManager)
def __init__(self, downloader, rate_limiter, primary_request_creators, secondary_request_creators):
self.downloader = downloader
self.rate_limiter = rate_limiter
self.primary_request_creators = primary_request_creators
self.secondary_request_creators = secondary_request_creators
self.peer_connections = {} # {Peer: {'connection': connection,
# 'request_creators': [IRequestCreator if using this connection]}}
self.connections_closing = {} # {Peer: deferred (fired when the connection is closed)}
self.next_manage_call = None
self._primary_request_creators = primary_request_creators
self._secondary_request_creators = secondary_request_creators
self._peer_connections = {} # {Peer: PeerConnectionHandler}
self._connections_closing = {} # {Peer: deferred (fired when the connection is closed)}
self._next_manage_call = None
def start(self):
from twisted.internet import reactor
if self.next_manage_call is not None and self.next_manage_call.active() is True:
self.next_manage_call.cancel()
self.next_manage_call = reactor.callLater(0, self._manage)
if self._next_manage_call is not None and self._next_manage_call.active() is True:
self._next_manage_call.cancel()
self._next_manage_call = reactor.callLater(0, self._manage)
return defer.succeed(True)
def stop(self):
if self.next_manage_call is not None and self.next_manage_call.active() is True:
self.next_manage_call.cancel()
self.next_manage_call = None
if self._next_manage_call is not None and self._next_manage_call.active() is True:
self._next_manage_call.cancel()
self._next_manage_call = None
closing_deferreds = []
for peer in self.peer_connections.keys():
for peer in self._peer_connections.keys():
def close_connection(p):
logging.info("Abruptly closing a connection to %s due to downloading being paused",
str(p))
if self.peer_connections[p]['factory'].p is not None:
d = self.peer_connections[p]['factory'].p.cancel_requests()
if self._peer_connections[p].factory.p is not None:
d = self._peer_connections[p].factory.p.cancel_requests()
else:
d = defer.succeed(True)
def disconnect_peer():
self.peer_connections[p]['connection'].disconnect()
if p in self.peer_connections:
del self.peer_connections[p]
d = defer.Deferred()
self.connections_closing[p] = d
self._connections_closing[p] = d
self._peer_connections[p].connection.disconnect()
if p in self._peer_connections:
del self._peer_connections[p]
return d
d.addBoth(lambda _: disconnect_peer())
@ -62,7 +68,7 @@ class ConnectionManager(object):
logging.debug("Trying to get the next request for peer %s", str(peer))
if not peer in self.peer_connections:
if not peer in self._peer_connections:
logging.debug("The peer has already been told to shut down.")
return defer.succeed(False)
@ -75,11 +81,11 @@ class ConnectionManager(object):
def check_if_request_sent(request_sent, request_creator):
if request_sent is False:
if request_creator in self.peer_connections[peer]['request_creators']:
self.peer_connections[peer]['request_creators'].remove(request_creator)
if request_creator in self._peer_connections[peer].request_creators:
self._peer_connections[peer].request_creators.remove(request_creator)
else:
if not request_creator in self.peer_connections[peer]['request_creators']:
self.peer_connections[peer]['request_creators'].append(request_creator)
if not request_creator in self._peer_connections[peer].request_creators:
self._peer_connections[peer].request_creators.append(request_creator)
return request_sent
def check_requests(requests):
@ -89,7 +95,7 @@ class ConnectionManager(object):
def get_secondary_requests_if_necessary(have_request):
if have_request is True:
ds = []
for s_r_c in self.secondary_request_creators:
for s_r_c in self._secondary_request_creators:
d = s_r_c.send_next_request(peer, protocol)
ds.append(d)
dl = defer.DeferredList(ds)
@ -100,7 +106,7 @@ class ConnectionManager(object):
ds = []
for p_r_c in self.primary_request_creators:
for p_r_c in self._primary_request_creators:
d = p_r_c.send_next_request(peer, protocol)
d.addErrback(handle_error)
d.addCallback(check_if_request_sent, p_r_c)
@ -112,11 +118,11 @@ class ConnectionManager(object):
return dl
def protocol_disconnected(self, peer, protocol):
if peer in self.peer_connections:
del self.peer_connections[peer]
if peer in self.connections_closing:
d = self.connections_closing[peer]
del self.connections_closing[peer]
if peer in self._peer_connections:
del self._peer_connections[peer]
if peer in self._connections_closing:
d = self._connections_closing[peer]
del self._connections_closing[peer]
d.callback(True)
def _rank_request_creator_connections(self):
@ -125,9 +131,9 @@ class ConnectionManager(object):
connections open that it likes
"""
def count_peers(request_creator):
return len([p for p in self.peer_connections.itervalues() if request_creator in p['request_creators']])
return len([p for p in self._peer_connections.itervalues() if request_creator in p.request_creators])
return sorted(self.primary_request_creators, key=count_peers)
return sorted(self._primary_request_creators, key=count_peers)
def _connect_to_peer(self, peer):
@ -136,10 +142,10 @@ class ConnectionManager(object):
if peer is not None:
logging.debug("Trying to connect to %s", str(peer))
factory = ClientProtocolFactory(peer, self.rate_limiter, self)
self._peer_connections[peer] = PeerConnectionHandler(self._primary_request_creators[:],
factory)
connection = reactor.connectTCP(peer.host, peer.port, factory)
self.peer_connections[peer] = {'connection': connection,
'request_creators': self.primary_request_creators[:],
'factory': factory}
self._peer_connections[peer].connection = connection
def _manage(self):
@ -162,16 +168,16 @@ class ConnectionManager(object):
if peers is None:
return None
for peer in peers:
if not peer in self.peer_connections:
if not peer in self._peer_connections:
logging.debug("Got a good peer. Returning peer %s", str(peer))
return peer
logging.debug("Couldn't find a good peer to connect to")
return None
if len(self.peer_connections) < MAX_CONNECTIONS_PER_STREAM:
if len(self._peer_connections) < MAX_CONNECTIONS_PER_STREAM:
ordered_request_creators = self._rank_request_creator_connections()
d = get_new_peers(ordered_request_creators)
d.addCallback(pick_best_peer)
d.addCallback(self._connect_to_peer)
self.next_manage_call = reactor.callLater(1, self._manage)
self._next_manage_call = reactor.callLater(1, self._manage)

View file

@ -445,10 +445,7 @@ class IQueryHandlerFactory(Interface):
"""
class IStreamDownloaderFactory(Interface):
"""
Construct IStreamDownloaders and provide options that will be passed to those IStreamDownloaders.
"""
class IStreamDownloaderOptions(Interface):
def get_downloader_options(self, sd_validator, payment_rate_manager):
"""
Return the list of options that can be used to modify IStreamDownloader behavior
@ -459,8 +456,28 @@ class IStreamDownloaderFactory(Interface):
@param payment_rate_manager: The payment rate manager currently in effect for the downloader
@type payment_rate_manager: PaymentRateManager
@return: [(option_description, default)]
@rtype: [(string, string)]
@return: [DownloadOption]
@rtype: [DownloadOption]
"""
class IStreamDownloaderFactory(Interface):
"""
Construct IStreamDownloaders and provide options that will be passed to those IStreamDownloaders.
"""
def can_download(self, sd_validator, payment_rate_manager):
"""
Decide whether the downloaders created by this factory can download the stream described by sd_validator
@param sd_validator: object containing stream metadata
@type sd_validator: object which implements IStreamDescriptorValidator interface
@param payment_rate_manager: The payment rate manager currently in effect for the downloader
@type payment_rate_manager: PaymentRateManager
@return: True if the downloaders can download the stream, False otherwise
@rtype: bool
"""
def make_downloader(self, sd_validator, options, payment_rate_manager):
@ -470,10 +487,10 @@ class IStreamDownloaderFactory(Interface):
@param sd_validator: object containing stream metadata which will be given to the IStreamDownloader
@type sd_validator: object which implements IStreamDescriptorValidator interface
@param options: a list of strings that will be used by the IStreamDownloaderFactory to
@param options: a list of values that will be used by the IStreamDownloaderFactory to
construct the IStreamDownloader. the options are in the same order as they were given
by get_downloader_options.
@type options: [string]
@type options: [Object]
@param payment_rate_manager: the PaymentRateManager which the IStreamDownloader should use.
@type payment_rate_manager: PaymentRateManager

View file

@ -3,7 +3,6 @@ import binascii
from zope.interface import implements
from lbrynet.core.DownloadOption import DownloadOption
from lbrynet.lbryfile.StreamDescriptor import save_sd_info
from lbrynet.cryptstream.client.CryptStreamDownloader import CryptStreamDownloader
from lbrynet.core.client.StreamProgressManager import FullStreamProgressManager
@ -11,6 +10,7 @@ from lbrynet.interfaces import IStreamDownloaderFactory
from lbrynet.lbryfile.client.LBRYFileMetadataHandler import LBRYFileMetadataHandler
import os
from twisted.internet import defer, threads, reactor
from distutils.spawn import find_executable
class LBRYFileDownloader(CryptStreamDownloader):
@ -94,26 +94,11 @@ class LBRYFileDownloaderFactory(object):
self.stream_info_manager = stream_info_manager
self.wallet = wallet
def get_downloader_options(self, sd_validator, payment_rate_manager):
options = [
DownloadOption(
[float, None],
"rate which will be paid for data (None means use application default)",
"data payment rate",
None
),
DownloadOption(
[bool],
"allow reuploading data downloaded for this file",
"allow upload",
True
),
]
return options
def can_download(self, sd_validator):
return True
def make_downloader(self, sd_validator, options, payment_rate_manager, **kwargs):
if options[0] is not None:
payment_rate_manager.float(options[0])
payment_rate_manager.min_blob_data_payment_rate = options[0]
upload_allowed = options[1]
def create_downloader(stream_hash):
@ -276,6 +261,9 @@ class LBRYFileOpener(LBRYFileDownloader):
class LBRYFileOpenerFactory(LBRYFileDownloaderFactory):
def can_download(self, sd_validator):
return bool(find_executable('vlc'))
def _make_downloader(self, stream_hash, payment_rate_manager, stream_info, upload_allowed):
return LBRYFileOpener(stream_hash, self.peer_finder, self.rate_limiter, self.blob_manager,
self.stream_info_manager, payment_rate_manager, self.wallet, upload_allowed)

View file

@ -0,0 +1,55 @@
from lbrynet.lbryfile.StreamDescriptor import LBRYFileStreamType, LBRYFileStreamDescriptorValidator
from lbrynet.core.DownloadOption import DownloadOption, DownloadChoice
def add_lbry_file_to_sd_identifier(sd_identifier):
sd_identifier.add_stream_type(LBRYFileStreamType, LBRYFileStreamDescriptorValidator, LBRYFileOptions())
class LBRYFileOptions(object):
def __init__(self):
pass
def get_downloader_options(self, sd_validator, payment_rate_manager):
prm = payment_rate_manager
def get_default_data_rate_description():
if prm.min_blob_data_payment_rate is None:
return "Application default (%s LBC/MB)" % str(prm.base.min_blob_data_payment_rate)
else:
return "%f LBC/MB" % prm.min_blob_data_payment_rate
rate_choices = []
rate_choices.append(DownloadChoice(prm.min_blob_data_payment_rate,
"No change - %s" % get_default_data_rate_description(),
"No change - %s" % get_default_data_rate_description()))
if prm.min_blob_data_payment_rate is not None:
rate_choices.append(DownloadChoice(None,
"Application default (%s LBC/MB)" % str(prm.base.min_blob_data_payment_rate),
"Application default (%s LBC/MB)" % str(prm.base.min_blob_data_payment_rate)))
rate_choices.append(DownloadChoice(float,
"Enter rate in LBC/MB",
"Enter rate in LBC/MB"))
options = [
DownloadOption(
rate_choices,
"Rate which will be paid for data",
"data payment rate",
prm.min_blob_data_payment_rate,
get_default_data_rate_description()
),
DownloadOption(
[
DownloadChoice(bool,
None,
None,
bool_options_description=("Allow", "Disallow")),
],
"Allow reuploading data downloaded for this file",
"allow upload",
True,
"Allow"
),
]
return options

View file

@ -2,7 +2,6 @@
Download LBRY Files from LBRYnet and save them to disk.
"""
from lbrynet.core.DownloadOption import DownloadOption
from zope.interface import implements
from lbrynet.core.client.StreamProgressManager import FullStreamProgressManager
from lbrynet.lbryfile.client.LBRYFileDownloader import LBRYFileSaver, LBRYFileDownloader
@ -117,22 +116,8 @@ class ManagedLBRYFileDownloaderFactory(object):
def __init__(self, lbry_file_manager):
self.lbry_file_manager = lbry_file_manager
def get_downloader_options(self, sd_validator, payment_rate_manager):
options = [
DownloadOption(
[float, None],
"rate which will be paid for data (None means use application default)",
"data payment rate",
None
),
DownloadOption(
[bool],
"allow reuploading data downloaded for this file",
"allow upload",
True
),
]
return options
def can_download(self, sd_validator):
return True
def make_downloader(self, sd_validator, options, payment_rate_manager):
data_rate = options[0]

View file

@ -7,7 +7,6 @@ import json
import leveldb
from lbrynet.lbryfile.StreamDescriptor import LBRYFileStreamDescriptorValidator
import os
from lbrynet.lbryfilemanager.LBRYFileDownloader import ManagedLBRYFileDownloader
from lbrynet.lbryfilemanager.LBRYFileDownloader import ManagedLBRYFileDownloaderFactory
@ -98,7 +97,6 @@ class LBRYFileManager(object):
def _add_to_sd_identifier(self):
downloader_factory = ManagedLBRYFileDownloaderFactory(self)
self.sd_identifier.add_stream_info_validator(LBRYFileStreamType, LBRYFileStreamDescriptorValidator)
self.sd_identifier.add_stream_downloader_factory(LBRYFileStreamType, downloader_factory)
def _start_lbry_files(self):

View file

@ -1,15 +1,12 @@
from lbrynet.core.StreamDescriptor import BlobStreamDescriptorWriter
from lbrynet.lbrylive.StreamDescriptor import get_sd_info, LiveStreamType, LBRYLiveStreamDescriptorValidator
from lbrynet.lbrylive.StreamDescriptor import get_sd_info
from lbrynet.cryptstream.CryptStreamCreator import CryptStreamCreator
from lbrynet.lbrylive.LiveBlob import LiveStreamBlobMaker
from lbrynet.lbrylive.PaymentRateManager import BaseLiveStreamPaymentRateManager
from lbrynet.core.cryptoutils import get_lbry_hash_obj, get_pub_key, sign_with_pass_phrase
from Crypto import Random
import binascii
import logging
from lbrynet.conf import CRYPTSD_FILE_EXTENSION
from lbrynet.conf import MIN_BLOB_INFO_PAYMENT_RATE
from lbrynet.lbrylive.client.LiveStreamDownloader import FullLiveStreamDownloaderFactory
from twisted.internet import interfaces, defer
from twisted.protocols.basic import FileSender
from zope.interface import implements
@ -174,16 +171,3 @@ class StdinStreamProducer(object):
def childConnectionLost(self, fd, reason):
self.stopProducing()
def add_live_stream_to_sd_identifier(session, stream_info_manager, sd_identifier):
downloader_factory = FullLiveStreamDownloaderFactory(session.peer_finder,
session.rate_limiter,
session.blob_manager,
stream_info_manager,
session.wallet,
BaseLiveStreamPaymentRateManager(
MIN_BLOB_INFO_PAYMENT_RATE
))
sd_identifier.add_stream_info_validator(LiveStreamType, LBRYLiveStreamDescriptorValidator)
sd_identifier.add_stream_downloader_factory(LiveStreamType, downloader_factory)

View file

@ -1,5 +1,4 @@
import binascii
from lbrynet.core.DownloadOption import DownloadOption
from lbrynet.cryptstream.client.CryptStreamDownloader import CryptStreamDownloader
from zope.interface import implements
from lbrynet.lbrylive.client.LiveStreamMetadataHandler import LiveStreamMetadataHandler
@ -9,6 +8,9 @@ from lbrynet.lbrylive.StreamDescriptor import save_sd_info
from lbrynet.lbrylive.PaymentRateManager import LiveStreamPaymentRateManager
from twisted.internet import defer, threads # , process
from lbrynet.interfaces import IStreamDownloaderFactory
from lbrynet.lbrylive.PaymentRateManager import BaseLiveStreamPaymentRateManager
from lbrynet.conf import MIN_BLOB_INFO_PAYMENT_RATE
from lbrynet.lbrylive.StreamDescriptor import LiveStreamType
class LiveStreamDownloader(CryptStreamDownloader):
@ -138,28 +140,8 @@ class FullLiveStreamDownloaderFactory(object):
self.wallet = wallet
self.default_payment_rate_manager = default_payment_rate_manager
def get_downloader_options(self, sd_validator, payment_rate_manager):
options = [
DownloadOption(
[float, None],
"rate which will be paid for data (None means use application default)",
"data payment rate",
None
),
DownloadOption(
[float, None],
"rate which will be paid for metadata (None means use application default)",
"metadata payment rate",
None
),
DownloadOption(
[bool],
"allow reuploading data downloaded for this file",
"allow upload",
True
),
]
return options
def can_download(self, sd_validator):
return True
def make_downloader(self, sd_validator, options, payment_rate_manager):
# TODO: check options for payment rate manager parameters
@ -178,3 +160,14 @@ class FullLiveStreamDownloaderFactory(object):
d.addCallback(create_downloader)
return d
def add_full_live_stream_downloader_to_sd_identifier(session, stream_info_manager, sd_identifier,
base_live_stream_payment_rate_manager):
downloader_factory = FullLiveStreamDownloaderFactory(session.peer_finder,
session.rate_limiter,
session.blob_manager,
stream_info_manager,
session.wallet,
base_live_stream_payment_rate_manager)
sd_identifier.add_stream_downloader_factory(LiveStreamType, downloader_factory)

View file

@ -0,0 +1,73 @@
from lbrynet.lbrylive.StreamDescriptor import LiveStreamType, LBRYLiveStreamDescriptorValidator
from lbrynet.core.DownloadOption import DownloadOption, DownloadChoice
def add_live_stream_to_sd_identifier(sd_identifier, base_live_stream_payment_rate_manager):
sd_identifier.add_stream_type(LiveStreamType, LBRYLiveStreamDescriptorValidator,
LiveStreamOptions(base_live_stream_payment_rate_manager))
class LiveStreamOptions(object):
def __init__(self, base_live_stream_payment_rate_manager):
self.base_live_stream_prm = base_live_stream_payment_rate_manager
def get_downloader_options(self, sd_validator, payment_rate_manager):
prm = payment_rate_manager
def get_default_data_rate_description():
if prm.min_blob_data_payment_rate is None:
return "Application default (%s LBC/MB)" % str(prm.base.min_blob_data_payment_rate)
else:
return "%f LBC/MB" % prm.min_blob_data_payment_rate
options = [
DownloadOption(
[
DownloadChoice(None,
"No change",
"No change"),
DownloadChoice(None,
"Application default (%s LBC/MB)" % str(prm.base.min_blob_data_payment_rate),
"Default (%s LBC/MB)" % str(prm.base.min_blob_data_payment_rate)),
DownloadChoice(float,
"Rate in LBC/MB",
"Rate in LBC/MB")
],
"rate which will be paid for data",
"data payment rate",
prm.min_blob_data_payment_rate,
get_default_data_rate_description()
),
DownloadOption(
[
DownloadChoice(None,
"No change",
"No change"),
DownloadChoice(None,
"Application default (%s LBC/MB)" % str(self.base_live_stream_prm.min_live_blob_info_payment_rate),
"Default (%s LBC/MB)" % str(self.base_live_stream_prm.min_live_blob_info_payment_rate)),
DownloadChoice(float,
"Rate in LBC/MB",
"Rate in LBC/MB")
],
"rate which will be paid for metadata",
"metadata payment rate",
None,
"Application default (%s LBC/MB)" % str(self.base_live_stream_prm.min_live_blob_info_payment_rate)
),
DownloadOption(
[
DownloadChoice(True,
"Allow reuploading data downloaded for this file",
"Allow reuploading"),
DownloadChoice(False,
"Disallow reuploading data downloaded for this file",
"Disallow reuploading")
],
"allow reuploading data downloaded for this file",
"allow upload",
True,
"Allow"
),
]
return options

View file

@ -13,6 +13,10 @@ class InvalidChoiceError(Exception):
pass
class InvalidValueError(Exception):
pass
class ControlHandlerFactory(object):
implements(IControlHandlerFactory)
@ -235,9 +239,11 @@ class AddStream(ControlHandler):
self.factories = None
self.factory = None
self.info_validator = None
self.options = None
self.options_left = []
self.options_chosen = []
self.current_option = None
self.current_choice = None
self.downloader = None
self.got_options_response = False
self.loading_failed = False
@ -274,18 +280,31 @@ class AddStream(ControlHandler):
return False, defer.succeed(self._show_factory_choices())
if self.got_options_response is False:
self.got_options_response = True
if line == 'y' or line == 'Y':
if self.options_left:
return False, defer.succeed(self._get_next_option_prompt())
self.options_chosen = [option.default for option in self.options_left]
self.options_left = []
return False, defer.succeed(self.line_prompt3)
if line == 'y' or line == 'Y' and self.options_left:
return False, defer.succeed(self._get_next_option_prompt())
else:
self.options_chosen = [option.default_value for option in self.options_left]
self.options_left = []
return False, defer.succeed(self.line_prompt3)
if self.current_option is not None:
try:
choice = self._get_choice_from_input(line)
except InvalidChoiceError:
return False, defer.succeed(self._get_next_option_prompt(invalid_response=True))
self.options_chosen.append(choice)
if self.current_choice is None:
try:
self.current_choice = self._get_choice_from_input(line)
except InvalidChoiceError:
return False, defer.succeed(self._get_next_option_prompt(invalid_choice=True))
choice = self.current_option.option_types[self.current_choice]
if choice.value == float or choice.value == bool:
return False, defer.succeed(self._get_choice_value_prompt())
else:
value = choice.value
else:
try:
value = self._get_value_for_choice(line)
except InvalidValueError:
return False, defer.succeed(self._get_choice_value_prompt(invalid_value=True))
self.options_chosen.append(value)
self.current_choice = None
self.current_option = None
self.options_left = self.options_left[1:]
if self.options_left:
return False, defer.succeed(self._get_next_option_prompt())
@ -299,23 +318,13 @@ class AddStream(ControlHandler):
return True, d
def _get_choice_from_input(self, line):
if line == "":
return self.current_option.default
for option_type in self.current_option.option_types:
if option_type == float:
try:
return float(line)
except ValueError:
pass
if option_type is None:
if line.lower() == "none":
return None
if option_type == bool:
if line.lower() == "true" or line.lower() == "t":
return True
if line.lower() == "false" or line.lower() == "f":
return False
raise InvalidChoiceError(line)
try:
choice_num = int(line)
except ValueError:
raise InvalidChoiceError()
if 0 <= choice_num < len(self.current_option.option_types):
return choice_num
raise InvalidChoiceError()
def _load_info_and_factories(self, sd_file):
return defer.fail(NotImplementedError())
@ -333,7 +342,7 @@ class AddStream(ControlHandler):
def _choose_factory(self, info_and_factories):
self.loading_info_and_factories_deferred = None
self.info_validator, self.factories = info_and_factories
self.info_validator, self.options, self.factories = info_and_factories
if len(self.factories) == 1:
self.factory = self.factories[0]
return self._show_info_and_options()
@ -346,38 +355,71 @@ class AddStream(ControlHandler):
return str(prompt)
def _show_info_and_options(self):
self.options_left = self.factory.get_downloader_options(self.info_validator,
self.options_left = self.options.get_downloader_options(self.info_validator,
self.payment_rate_manager)
prompt = "Stream info:\n"
for info_line in self.info_validator.info_to_show():
prompt += info_line[0] + ": " + info_line[1] + "\n"
prompt += "\nOptions:\n"
for option in self.options_left:
prompt += option.long_description + ": " + str(option.default) + "\n"
prompt += option.long_description + ": " + str(option.default_value_description) + "\n"
prompt += "\nModify options? (y/n)"
return str(prompt)
def _get_option_type_description(self, option_type):
if option_type == float:
return "floating point number (e.g. 1.0)"
if option_type == bool:
return "True or False"
if option_type is None:
return "None"
def _get_list_of_option_types(self):
options_string = ""
for i, option_type in enumerate(self.current_option.option_types):
options_string += "[%s] %s\n" % (str(i), option_type.long_description)
options_string += "Enter choice:"
return options_string
def _get_next_option_prompt(self, invalid_response=False):
assert len(self.options_left), "Something went wrong. There were no options left"
choice = self.options_left[0]
def _get_choice_value_prompt(self, invalid_value=False):
choice = self.current_option.option_types[self.current_choice]
choice_string = ""
if invalid_response is True:
if invalid_value is True:
"Invalid value entered. Try again.\n"
if choice.short_description is not None:
choice_string += choice.short_description + "\n"
if choice.value == float:
choice_string += "Enter floating point number (e.g. 1.0):"
elif choice.value == bool:
true_string = "Yes"
false_string = "No"
if choice.bool_options_description is not None:
true_string, false_string = choice.bool_options_description
choice_string += "[0] %s\n[1] %s\nEnter choice:" % (true_string, false_string)
else:
NotImplementedError()
return choice_string
def _get_value_for_choice(self, input):
choice = self.current_option.option_types[self.current_choice]
if choice.value == float:
try:
return float(input)
except ValueError:
raise InvalidValueError()
elif choice.value == bool:
if input == "0":
return True
elif input == "1":
return False
raise InvalidValueError()
raise NotImplementedError()
def _get_next_option_prompt(self, invalid_choice=False):
assert len(self.options_left), "Something went wrong. There were no options left"
self.current_option = self.options_left[0]
choice_string = ""
if invalid_choice is True:
choice_string += "Invalid response entered. Try again.\n"
choice_string += choice.long_description + "\n"
choice_string += "Valid inputs:\n"
for option_type in choice.option_types:
choice_string += "\t" + self._get_option_type_description(option_type) + "\n"
choice_string += "Leave blank for default (" + str(choice.default) + ")\n"
choice_string += "Enter choice:"
self.current_option = choice
choice_string += self.current_option.long_description + "\n"
if len(self.current_option.option_types) > 1:
choice_string += self._get_list_of_option_types()
elif len(self.current_option.option_types) == 1:
self.current_choice = 0
choice_string += self._get_choice_value_prompt()
return choice_string
def _start_download(self):

View file

@ -15,6 +15,7 @@ from lbrynet.core.server.BlobAvailabilityHandler import BlobAvailabilityHandlerF
from lbrynet.core.server.BlobRequestHandler import BlobRequestHandlerFactory
from lbrynet.core.server.ServerProtocol import ServerProtocolFactory
from lbrynet.core.PTCWallet import PTCWallet
from lbrynet.lbryfile.client.LBRYFileOptions import add_lbry_file_to_sd_identifier
from lbrynet.lbryfile.client.LBRYFileDownloader import LBRYFileOpenerFactory
from lbrynet.lbryfile.StreamDescriptor import LBRYFileStreamType
from lbrynet.lbryfile.LBRYFileMetadataManager import DBLBRYFileMetadataManager, TempLBRYFileMetadataManager
@ -77,6 +78,7 @@ class LBRYConsole():
d = threads.deferToThread(self._create_directory)
d.addCallback(lambda _: self._get_settings())
d.addCallback(lambda _: self._get_session())
d.addCallback(lambda _: add_lbry_file_to_sd_identifier(self.sd_identifier))
d.addCallback(lambda _: self._setup_lbry_file_manager())
d.addCallback(lambda _: self._setup_lbry_file_opener())
d.addCallback(lambda _: self._setup_control_handlers())

View file

@ -17,7 +17,8 @@ from lbrynet.core.StreamDescriptor import StreamDescriptorIdentifier
from lbrynet.core.PaymentRateManager import PaymentRateManager
from lbrynet.lbryfile.LBRYFileMetadataManager import TempLBRYFileMetadataManager
from lbrynet.core import StreamDescriptor
from lbrynet.lbryfile.StreamDescriptor import LBRYFileStreamType, LBRYFileStreamDescriptorValidator
from lbrynet.lbryfile.client.LBRYFileOptions import add_lbry_file_to_sd_identifier
from lbrynet.lbryfile.StreamDescriptor import LBRYFileStreamType
import requests
@ -101,7 +102,7 @@ class LBRYDownloader(object):
return defer.succeed(True)
def _setup_stream_identifier(self):
self.sd_identifier.add_stream_info_validator(LBRYFileStreamType, LBRYFileStreamDescriptorValidator)
add_lbry_file_to_sd_identifier(self.sd_identifier)
file_saver_factory = LBRYFileSaverFactory(self.session.peer_finder, self.session.rate_limiter,
self.session.blob_manager, self.stream_info_manager,
self.session.wallet, self.download_directory)
@ -184,7 +185,7 @@ class LBRYDownloader(object):
return stream_name, stream_size
def choose_download_factory(info_and_factories):
info_validator, factories = info_and_factories
info_validator, options, factories = info_and_factories
stream_name, stream_size = get_info_from_validator(info_validator)
if isinstance(stream_size, (int, long)):
price = payment_rate_manager.get_effective_min_blob_data_payment_rate()
@ -192,26 +193,30 @@ class LBRYDownloader(object):
else:
estimated_cost = "unknown"
stream_frame.show_stream_metadata(stream_name, stream_size, estimated_cost)
stream_frame.show_stream_metadata(stream_name, stream_size)
available_options = options.get_downloader_options(info_validator, payment_rate_manager)
stream_frame.show_download_options(available_options)
get_downloader_d = defer.Deferred()
def create_downloader(f):
def create_downloader(f, chosen_options):
def fire_get_downloader_d(downloader):
if not get_downloader_d.called:
get_downloader_d.callback(downloader)
stream_frame.disable_download_buttons()
download_options = [o.default for o in f.get_downloader_options(info_validator, payment_rate_manager)]
d = f.make_downloader(info_validator, download_options,
d = f.make_downloader(info_validator, chosen_options,
payment_rate_manager)
d.addCallback(fire_get_downloader_d)
for factory in factories:
def choose_factory(f=factory):
create_downloader(f)
chosen_options = stream_frame.get_chosen_options()
create_downloader(f, chosen_options)
stream_frame.add_download_factory(factory, choose_factory)
@ -301,9 +306,9 @@ class StreamFrame(object):
self.uri_label.grid(row=0, column=0, sticky=tk.W)
if os.name == "nt":
close_cursor = ""
self.button_cursor = ""
else:
close_cursor = "hand1"
self.button_cursor = "hand1"
close_file_name = "close2.gif"
try:
@ -316,7 +321,7 @@ class StreamFrame(object):
file=close_file
)
self.close_button = ttk.Button(
self.stream_frame_header, command=self.cancel, style="Stop.TButton", cursor=close_cursor
self.stream_frame_header, command=self.cancel, style="Stop.TButton", cursor=self.button_cursor
)
self.close_button.config(image=self.close_picture)
self.close_button.grid(row=0, column=1, sticky=tk.E + tk.N)
@ -334,26 +339,50 @@ class StreamFrame(object):
self.stream_frame_body.grid_columnconfigure(0, weight=1)
self.info_frame = ttk.Frame(self.stream_frame_body, style="D.TFrame")
self.info_frame.grid(sticky=tk.W + tk.E, row=1)
self.info_frame.grid_columnconfigure(0, weight=1)
self.metadata_frame = ttk.Frame(self.info_frame, style="E.TFrame")
self.metadata_frame.grid(sticky=tk.W + tk.E)
self.metadata_frame = ttk.Frame(self.stream_frame_body, style="D.TFrame")
self.metadata_frame.grid(sticky=tk.W + tk.E, row=1)
self.metadata_frame.grid_columnconfigure(0, weight=1)
self.outer_button_frame = ttk.Frame(self.stream_frame_body, style="D.TFrame")
self.outer_button_frame.grid(sticky=tk.W + tk.E, row=2)
self.options_frame = ttk.Frame(self.stream_frame_body, style="D.TFrame")
self.button_frame = ttk.Frame(self.outer_button_frame, style="E.TFrame")
self.button_frame.pack(side=tk.TOP)
self.outer_button_frame = ttk.Frame(self.stream_frame_body, style="D.TFrame")
self.outer_button_frame.grid(sticky=tk.W + tk.E, row=4)
show_options_picture_file_name = "show_options.gif"
try:
show_options_picture_file = os.path.join(os.path.dirname(__file__),
show_options_picture_file_name)
except NameError:
show_options_picture_file = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])),
"lbrynet", "lbrynet_downloader_gui",
show_options_picture_file_name)
self.show_options_picture = tk.PhotoImage(
file=show_options_picture_file
)
hide_options_picture_file_name = "hide_options.gif"
try:
hide_options_picture_file = os.path.join(os.path.dirname(__file__),
hide_options_picture_file_name)
except NameError:
hide_options_picture_file = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])),
"lbrynet", "lbrynet_downloader_gui",
hide_options_picture_file_name)
self.hide_options_picture = tk.PhotoImage(
file=hide_options_picture_file
)
self.show_options_button = None
self.status_label = None
self.name_label = None
self.bytes_downloaded_label = None
self.bytes_outputted_label = None
self.button_frame = None
self.download_buttons = []
self.option_frames = []
self.name_font = None
self.description_label = None
self.file_name_frame = None
@ -416,7 +445,7 @@ class StreamFrame(object):
return "%.1f %s" % (round((stream_size * 1.0 / factor), 1), units)
return stream_size
def show_stream_metadata(self, stream_name, stream_size, estimated_cost):
def show_stream_metadata(self, stream_name, stream_size):
if self.status_label is not None:
self.status_label.destroy()
@ -436,19 +465,6 @@ class StreamFrame(object):
)
file_name_label.grid(row=0, column=3)
self.outer_button_frame = ttk.Frame(self.stream_frame_body, style="D.TFrame")
self.outer_button_frame.grid(sticky=tk.W + tk.E, row=2)
self.cost_frame = ttk.Frame(self.outer_button_frame, style="F.TFrame")
self.cost_frame.grid(row=0, column=0, sticky=tk.W+tk.N, pady=(0, 12))
self.cost_label = ttk.Label(
self.cost_frame,
text=locale.format_string("%.2f LBC", (round(estimated_cost, 2),), grouping=True),
foreground="red"
)
self.cost_label.grid(row=0, column=1, padx=(1, 0))
self.button_frame = ttk.Frame(self.outer_button_frame, style="E.TFrame")
self.button_frame.grid(row=0, column=1)
@ -457,13 +473,9 @@ class StreamFrame(object):
self.outer_button_frame.grid_columnconfigure(2, weight=1, uniform="buttons")
def add_download_factory(self, factory, download_func):
if os.name == "nt":
button_cursor = ""
else:
button_cursor = "hand1"
download_button = ttk.Button(
self.button_frame, text=factory.get_description(), command=download_func,
style='LBRY.TButton', cursor=button_cursor
style='LBRY.TButton', cursor=self.button_cursor
)
self.download_buttons.append(download_button)
download_button.grid(row=0, column=len(self.download_buttons) - 1, padx=5, pady=(1, 2))
@ -477,11 +489,160 @@ class StreamFrame(object):
download_button.destroy()
self.download_buttons = []
def get_option_widget(self, option_type, option_frame):
if option_type.value == float:
entry_frame = ttk.Frame(
option_frame,
style="H.TFrame"
)
entry_frame.grid()
col = 0
if option_type.short_description is not None:
entry_label = ttk.Label(
entry_frame,
#text=option_type.short_description
text=""
)
entry_label.grid(row=0, column=0, sticky=tk.W)
col = 1
entry = ttk.Entry(
entry_frame,
width=10,
style="Float.TEntry"
)
entry_frame.entry = entry
entry.grid(row=0, column=col, sticky=tk.W)
return entry_frame
if option_type.value == bool:
bool_frame = ttk.Frame(
option_frame,
style="H.TFrame"
)
bool_frame.chosen_value = tk.BooleanVar()
true_text = "True"
false_text = "False"
if option_type.bool_options_description is not None:
true_text, false_text = option_type.bool_options_description
true_radio_button = ttk.Radiobutton(
bool_frame, text=true_text, variable=bool_frame.chosen_value, value=True
)
true_radio_button.grid(row=0, sticky=tk.W)
false_radio_button = ttk.Radiobutton(
bool_frame, text=false_text, variable=bool_frame.chosen_value, value=False
)
false_radio_button.grid(row=1, sticky=tk.W)
return bool_frame
label = ttk.Label(
option_frame,
text=""
)
return label
def show_download_options(self, options):
left_padding = 20
for option in options:
f = ttk.Frame(
self.options_frame,
style="E.TFrame"
)
f.grid(sticky=tk.W + tk.E, padx=left_padding)
self.option_frames.append((option, f))
description_label = ttk.Label(
f,
text=option.long_description
)
description_label.grid(row=0, sticky=tk.W)
if len(option.option_types) > 1:
f.chosen_type = tk.IntVar()
choices_frame = ttk.Frame(
f,
style="F.TFrame"
)
f.choices_frame = choices_frame
choices_frame.grid(row=1, sticky=tk.W, padx=left_padding)
choices_frame.choices = []
for i, option_type in enumerate(option.option_types):
choice_frame = ttk.Frame(
choices_frame,
style="G.TFrame"
)
choice_frame.grid(sticky=tk.W)
option_text = ""
if option_type.short_description is not None:
option_text = option_type.short_description
option_radio_button = ttk.Radiobutton(
choice_frame, text=option_text, variable=f.chosen_type, value=i
)
option_radio_button.grid(row=0, column=0, sticky=tk.W)
option_widget = self.get_option_widget(option_type, choice_frame)
option_widget.grid(row=0, column=1, sticky=tk.W)
choices_frame.choices.append(option_widget)
if i == 0:
option_radio_button.invoke()
else:
choice_frame = ttk.Frame(
f,
style="F.TFrame"
)
choice_frame.grid(sticky=tk.W, padx=left_padding)
option_widget = self.get_option_widget(option.option_types[0], choice_frame)
option_widget.grid(row=0, column=0, sticky=tk.W)
f.option_widget = option_widget
self.show_options_button = ttk.Button(
self.stream_frame_body, command=self._toggle_show_options, style="Stop.TButton",
cursor=self.button_cursor
)
self.show_options_button.config(image=self.show_options_picture)
self.show_options_button.grid(sticky=tk.W, row=2, column=0)
def _get_chosen_option(self, option_type, option_widget):
if option_type.value == float:
return float(option_widget.entry.get())
if option_type.value == bool:
return option_widget.chosen_value.get()
return option_type.value
def get_chosen_options(self):
chosen_options = []
for o, f in self.option_frames:
if len(o.option_types) > 1:
chosen_index = f.chosen_type.get()
option_type = o.option_types[chosen_index]
option_widget = f.choices_frame.choices[chosen_index]
chosen_options.append(self._get_chosen_option(option_type, option_widget))
else:
option_type = o.option_types[0]
option_widget = f.option_widget
chosen_options.append(self._get_chosen_option(option_type, option_widget))
return chosen_options
def _toggle_show_options(self):
if self.options_frame.winfo_ismapped():
self.show_options_button.config(image=self.show_options_picture)
self.options_frame.grid_forget()
else:
self.show_options_button.config(image=self.hide_options_picture)
self.options_frame.grid(sticky=tk.W + tk.E, row=3)
def show_progress(self, total_bytes, bytes_left_to_download, bytes_left_to_output, points_paid,
points_remaining):
if self.bytes_outputted_label is None:
self.remove_download_buttons()
self.button_frame.destroy()
for option, frame in self.option_frames:
frame.destroy()
self.options_frame.destroy()
self.show_options_button.destroy()
self.cost_frame = ttk.Frame(self.outer_button_frame, style="F.TFrame")
self.cost_frame.grid(row=0, column=0, sticky=tk.W+tk.N, pady=(0, 12))
self.cost_label = ttk.Label(
self.cost_frame,
text="",
foreground="red"
)
self.cost_label.grid(row=0, column=1, padx=(1, 0))
self.outer_button_frame.grid_columnconfigure(2, weight=0, uniform="")
self.bytes_outputted_label = ttk.Label(
@ -667,6 +828,7 @@ class App(object):
ttk.Style().configure("Lookup.LBRY.TButton", padding=lookup_button_padding)
ttk.Style().configure("Stop.TButton", padding=1, background="#FFFFFF", relief="flat", borderwidth=0)
ttk.Style().configure("TEntry", padding=11)
ttk.Style().configure("Float.TEntry", padding=2)
#ttk.Style().configure("A.TFrame", background="red")
#ttk.Style().configure("B.TFrame", background="green")
#ttk.Style().configure("B2.TFrame", background="#80FF80")
@ -674,6 +836,8 @@ class App(object):
#ttk.Style().configure("D.TFrame", background="blue")
#ttk.Style().configure("E.TFrame", background="yellow")
#ttk.Style().configure("F.TFrame", background="#808080")
#ttk.Style().configure("G.TFrame", background="#FF80FF")
#ttk.Style().configure("H.TFrame", background="#0080FF")
#ttk.Style().configure("LBRY.TProgressbar", background="#104639", orient="horizontal", thickness=5)
#ttk.Style().configure("LBRY.TProgressbar")
#ttk.Style().layout("Horizontal.LBRY.TProgressbar", ttk.Style().layout("Horizontal.TProgressbar"))

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 B

View file

@ -36,6 +36,8 @@ setup(name='lbrynet',
'lbrynet/lbrynet_downloader_gui/lbry-dark-icon.xbm',
'lbrynet/lbrynet_downloader_gui/lbry-dark-icon.ico',
'lbrynet/lbrynet_downloader_gui/drop_down.gif',
'lbrynet/lbrynet_downloader_gui/show_options.gif',
'lbrynet/lbrynet_downloader_gui/hide_options.gif',
]
)
]

View file

@ -9,7 +9,7 @@ from Crypto import Random
from Crypto.Hash import MD5
from lbrynet.conf import MIN_BLOB_DATA_PAYMENT_RATE
from lbrynet.conf import MIN_BLOB_INFO_PAYMENT_RATE
from lbrynet.lbrylive.LiveStreamCreator import FileLiveStreamCreator, add_live_stream_to_sd_identifier
from lbrynet.lbrylive.LiveStreamCreator import FileLiveStreamCreator
from lbrynet.lbrylive.PaymentRateManager import BaseLiveStreamPaymentRateManager
from lbrynet.lbrylive.PaymentRateManager import LiveStreamPaymentRateManager
from lbrynet.lbrylive.LiveStreamMetadataManager import DBLiveStreamMetadataManager
@ -24,6 +24,7 @@ from lbrynet.core.StreamDescriptor import BlobStreamDescriptorWriter
from lbrynet.core.StreamDescriptor import StreamDescriptorIdentifier
from lbrynet.core.StreamDescriptor import download_sd_blob
from lbrynet.lbryfilemanager.LBRYFileCreator import create_lbry_file
from lbrynet.lbryfile.client.LBRYFileOptions import add_lbry_file_to_sd_identifier
from lbrynet.lbryfile.StreamDescriptor import get_sd_info
from twisted.internet import defer, threads, task
from twisted.trial.unittest import TestCase
@ -35,6 +36,8 @@ from lbrynet.core.server.BlobAvailabilityHandler import BlobAvailabilityHandlerF
from lbrynet.core.server.BlobRequestHandler import BlobRequestHandlerFactory
from lbrynet.core.server.ServerProtocol import ServerProtocolFactory
from lbrynet.lbrylive.server.LiveBlobInfoQueryHandler import CryptBlobInfoQueryHandlerFactory
from lbrynet.lbrylive.client.LiveStreamOptions import add_live_stream_to_sd_identifier
from lbrynet.lbrylive.client.LiveStreamDownloader import add_full_live_stream_downloader_to_sd_identifier
log_format = "%(funcName)s(): %(message)s"
@ -248,6 +251,7 @@ def start_lbry_uploader(sd_hash_queue, kill_event, dead_event):
def start_all():
d = session.setup()
d.addCallback(lambda _: add_lbry_file_to_sd_identifier(sd_identifier))
d.addCallback(lambda _: lbry_file_manager.setup())
d.addCallback(lambda _: start_server())
d.addCallback(lambda _: create_stream())
@ -437,7 +441,12 @@ def start_live_server(sd_hash_queue, kill_event, dead_event):
return d
def enable_live_stream():
return add_live_stream_to_sd_identifier(session, stream_info_manager, sd_identifier)
base_live_stream_payment_rate_manager = BaseLiveStreamPaymentRateManager(
MIN_BLOB_INFO_PAYMENT_RATE
)
add_live_stream_to_sd_identifier(sd_identifier, base_live_stream_payment_rate_manager)
add_full_live_stream_downloader_to_sd_identifier(session, stream_info_manager, sd_identifier,
base_live_stream_payment_rate_manager)
def run_server():
d = session.setup()
@ -670,9 +679,9 @@ class TestTransfer(TestCase):
self.lbry_file_manager = LBRYFileManager(self.session, self.stream_info_manager, sd_identifier)
def make_downloader(info_and_factories, prm):
info_validator, factories = info_and_factories
options = [o.default for o in factories[0].get_downloader_options(info_validator, prm)]
return factories[0].make_downloader(info_validator, options, prm)
info_validator, options, factories = info_and_factories
chosen_options = [o.default_value for o in options.get_downloader_options(info_validator, prm)]
return factories[0].make_downloader(info_validator, chosen_options, prm)
def download_file(sd_hash):
prm = PaymentRateManager(self.session.base_payment_rate_manager)
@ -693,6 +702,7 @@ class TestTransfer(TestCase):
logging.debug("Starting the transfer")
d = self.session.setup()
d.addCallback(lambda _: add_lbry_file_to_sd_identifier(sd_identifier))
d.addCallback(lambda _: self.lbry_file_manager.setup())
d.addCallback(lambda _: download_file(sd_hash))
d.addCallback(lambda _: check_md5_sum())
@ -750,9 +760,9 @@ class TestTransfer(TestCase):
d = self.wait_for_hash_from_queue(sd_hash_queue)
def create_downloader(info_and_factories, prm):
info_validator, factories = info_and_factories
options = [o.default for o in factories[0].get_downloader_options(info_validator, prm)]
return factories[0].make_downloader(info_validator, options, prm)
info_validator, options, factories = info_and_factories
chosen_options = [o.default_value for o in options.get_downloader_options(info_validator, prm)]
return factories[0].make_downloader(info_validator, chosen_options, prm)
def start_lbry_file(lbry_file):
lbry_file = lbry_file
@ -776,7 +786,14 @@ class TestTransfer(TestCase):
return d
def enable_live_stream():
return add_live_stream_to_sd_identifier(self.session, self.stream_info_manager, sd_identifier)
base_live_stream_payment_rate_manager = BaseLiveStreamPaymentRateManager(
MIN_BLOB_INFO_PAYMENT_RATE
)
add_live_stream_to_sd_identifier(sd_identifier,
base_live_stream_payment_rate_manager)
add_full_live_stream_downloader_to_sd_identifier(self.session, self.stream_info_manager,
sd_identifier,
base_live_stream_payment_rate_manager)
d.addCallback(do_download)
@ -941,6 +958,7 @@ class TestStreamify(TestCase):
d = self.session.setup()
d.addCallback(lambda _: self.stream_info_manager.setup())
d.addCallback(lambda _: add_lbry_file_to_sd_identifier(sd_identifier))
d.addCallback(lambda _: self.lbry_file_manager.setup())
def verify_equal(sd_info):
@ -1017,6 +1035,7 @@ class TestStreamify(TestCase):
d = self.session.setup()
d.addCallback(lambda _: self.stream_info_manager.setup())
d.addCallback(lambda _: add_lbry_file_to_sd_identifier(sd_identifier))
d.addCallback(lambda _: self.lbry_file_manager.setup())
d.addCallback(lambda _: create_stream())
d.addCallback(combine_stream)