forked from premiere/premiere-libtorrent
Fix python client (#1512)
extend python test to include examples. add piece index and block index python bindings
This commit is contained in:
parent
4ddd4b72c6
commit
32e0028e32
|
@ -218,15 +218,12 @@ def main():
|
|||
if options.max_download_rate <= 0:
|
||||
options.max_download_rate = -1
|
||||
|
||||
settings = lt.session_settings()
|
||||
settings.user_agent = 'python_client/' + lt.version
|
||||
|
||||
ses = lt.session()
|
||||
ses.set_download_rate_limit(int(options.max_download_rate))
|
||||
ses.set_upload_rate_limit(int(options.max_upload_rate))
|
||||
ses.listen_on(options.port, options.port + 10)
|
||||
ses.set_settings(settings)
|
||||
ses.set_alert_mask(0xfffffff)
|
||||
ses = lt.session({'user_agent': 'python_client/' + lt.__version__,
|
||||
'listen_interfaces':'0.0.0.0:' + str(options.port),
|
||||
'download_rate_limit': int(options.max_download_rate),
|
||||
'upload_rate_limit': int(options.max_upload_rate),
|
||||
'alert_mask' : 0xfffffff
|
||||
})
|
||||
|
||||
if options.proxy_host != '':
|
||||
ps = lt.proxy_settings()
|
||||
|
@ -281,14 +278,13 @@ def main():
|
|||
out = ''
|
||||
|
||||
for h in handles:
|
||||
if h.has_metadata():
|
||||
name = h.get_torrent_info().name()[:40]
|
||||
s = h.status()
|
||||
if s.has_metadata:
|
||||
name = h.torrent_file().name()[:40]
|
||||
else:
|
||||
name = '-'
|
||||
out += 'name: %-40s\n' % name
|
||||
|
||||
s = h.status()
|
||||
|
||||
if s.state != lt.torrent_status.seeding:
|
||||
state_str = ['queued', 'checking', 'downloading metadata',
|
||||
'downloading', 'finished', 'seeding',
|
||||
|
@ -335,14 +331,7 @@ def main():
|
|||
write_line(console, '(q)uit), (p)ause), (u)npause), (r)eannounce\n')
|
||||
write_line(console, 76 * '-' + '\n')
|
||||
|
||||
while 1:
|
||||
a = ses.pop_alert()
|
||||
if not a:
|
||||
break
|
||||
alerts.append(a)
|
||||
|
||||
if len(alerts) > 8:
|
||||
del alerts[:len(alerts) - 8]
|
||||
alerts = ses.pop_alerts()
|
||||
|
||||
for a in alerts:
|
||||
if type(a) == str:
|
||||
|
@ -369,7 +358,7 @@ def main():
|
|||
|
||||
ses.pause()
|
||||
for h in handles:
|
||||
if not h.is_valid() or not h.has_metadata():
|
||||
if not h.is_valid() or not s.has_metadata:
|
||||
continue
|
||||
data = lt.bencode(h.write_resume_data())
|
||||
open(os.path.join(options.save_path, h.get_torrent_info().name() +
|
||||
|
|
|
@ -20,6 +20,11 @@ fs = libtorrent.file_storage()
|
|||
|
||||
parent_input = os.path.split(input)[0]
|
||||
|
||||
# if we have a single file, use it because os.walk does not work on a single files
|
||||
if os.path.isfile(input):
|
||||
size = os.path.getsize(input)
|
||||
fs.add_file(input, size)
|
||||
|
||||
for root, dirs, files in os.walk(input):
|
||||
# skip directories starting with .
|
||||
if os.path.split(root)[1][0] == '.':
|
||||
|
@ -48,8 +53,8 @@ t = libtorrent.create_torrent(fs, 0, 4 * 1024 * 1024)
|
|||
t.add_tracker(sys.argv[2])
|
||||
t.set_creator('libtorrent %s' % libtorrent.__version__)
|
||||
|
||||
libtorrent.set_piece_hashes(t, parent_input, lambda x: sys.stderr.write('.'))
|
||||
sys.stderr.write('\n')
|
||||
libtorrent.set_piece_hashes(t, parent_input, lambda x: sys.stdout.write('.'))
|
||||
sys.stdout.write('\n')
|
||||
|
||||
f = open('out.torrent', 'wb+')
|
||||
f.write(libtorrent.bencode(t.generate()))
|
||||
|
|
|
@ -8,14 +8,14 @@ import libtorrent as lt
|
|||
import time
|
||||
import sys
|
||||
|
||||
ses = lt.session()
|
||||
ses.listen_on(6881, 6891)
|
||||
ses = lt.session({'listen_interfaces':'0.0.0.0:6881'})
|
||||
|
||||
info = lt.torrent_info(sys.argv[1])
|
||||
h = ses.add_torrent({'ti': info, 'save_path': '.'})
|
||||
print('starting', h.name())
|
||||
s = h.status()
|
||||
print('starting', s.name)
|
||||
|
||||
while (not h.is_seed()):
|
||||
while (not s.is_seeding):
|
||||
s = h.status()
|
||||
|
||||
state_str = [
|
||||
|
|
|
@ -356,7 +356,7 @@ void bind_alert()
|
|||
|
||||
class_<hash_failed_alert, bases<torrent_alert>, noncopyable>(
|
||||
"hash_failed_alert", no_init)
|
||||
.def_readonly("piece_index", &hash_failed_alert::piece_index)
|
||||
.add_property("piece_index", make_getter(&hash_failed_alert::piece_index, by_value()))
|
||||
;
|
||||
|
||||
class_<peer_ban_alert, bases<peer_alert>, noncopyable>(
|
||||
|
@ -389,13 +389,13 @@ void bind_alert()
|
|||
|
||||
class_<piece_finished_alert, bases<torrent_alert>, noncopyable>(
|
||||
"piece_finished_alert", no_init)
|
||||
.def_readonly("piece_index", &piece_finished_alert::piece_index)
|
||||
.add_property("piece_index", make_getter(&piece_finished_alert::piece_index, by_value()))
|
||||
;
|
||||
|
||||
class_<block_finished_alert, bases<peer_alert>, noncopyable>(
|
||||
"block_finished_alert", no_init)
|
||||
.def_readonly("block_index", &block_finished_alert::block_index)
|
||||
.def_readonly("piece_index", &block_finished_alert::piece_index)
|
||||
.add_property("block_index", make_getter(&block_finished_alert::block_index, by_value()))
|
||||
.add_property("piece_index", make_getter(&block_finished_alert::piece_index, by_value()))
|
||||
;
|
||||
|
||||
class_<block_downloading_alert, bases<peer_alert>, noncopyable>(
|
||||
|
@ -403,8 +403,8 @@ void bind_alert()
|
|||
#ifndef TORRENT_NO_DEPRECATE
|
||||
.def_readonly("peer_speedmsg", &block_downloading_alert::peer_speedmsg)
|
||||
#endif
|
||||
.def_readonly("block_index", &block_downloading_alert::block_index)
|
||||
.def_readonly("piece_index", &block_downloading_alert::piece_index)
|
||||
.add_property("block_index", make_getter(&block_downloading_alert::block_index, by_value()))
|
||||
.add_property("piece_index", make_getter(&block_downloading_alert::piece_index, by_value()))
|
||||
;
|
||||
|
||||
class_<storage_moved_alert, bases<torrent_alert>, noncopyable>(
|
||||
|
@ -693,20 +693,20 @@ void bind_alert()
|
|||
|
||||
class_<request_dropped_alert, bases<peer_alert>, noncopyable>(
|
||||
"request_dropped_alert", no_init)
|
||||
.def_readonly("block_index", &request_dropped_alert::block_index)
|
||||
.def_readonly("piece_index", &request_dropped_alert::piece_index)
|
||||
.add_property("block_index", make_getter(&request_dropped_alert::block_index, by_value()))
|
||||
.add_property("piece_index", make_getter(&request_dropped_alert::piece_index, by_value()))
|
||||
;
|
||||
|
||||
class_<block_timeout_alert, bases<peer_alert>, noncopyable>(
|
||||
"block_timeout_alert", no_init)
|
||||
.def_readonly("block_index", &block_timeout_alert::block_index)
|
||||
.def_readonly("piece_index", &block_timeout_alert::piece_index)
|
||||
.add_property("block_index", make_getter(&block_timeout_alert::block_index, by_value()))
|
||||
.add_property("piece_index", make_getter(&block_timeout_alert::piece_index, by_value()))
|
||||
;
|
||||
|
||||
class_<unwanted_block_alert, bases<peer_alert>, noncopyable>(
|
||||
"unwanted_block_alert", no_init)
|
||||
.def_readonly("block_index", &unwanted_block_alert::block_index)
|
||||
.def_readonly("piece_index", &unwanted_block_alert::piece_index)
|
||||
.add_property("block_index", make_getter(&unwanted_block_alert::block_index, by_value()))
|
||||
.add_property("piece_index", make_getter(&unwanted_block_alert::piece_index, by_value()))
|
||||
;
|
||||
|
||||
class_<torrent_delete_failed_alert, bases<torrent_alert>, noncopyable>(
|
||||
|
|
|
@ -47,6 +47,7 @@ list get_pieces(peer_info const& pi)
|
|||
return ret;
|
||||
}
|
||||
|
||||
using by_value = return_value_policy<return_by_value>;
|
||||
void bind_peer_info()
|
||||
{
|
||||
scope pi = class_<peer_info>("peer_info")
|
||||
|
@ -82,8 +83,8 @@ void bind_peer_info()
|
|||
.def_readonly("download_queue_length", &peer_info::download_queue_length)
|
||||
.def_readonly("upload_queue_length", &peer_info::upload_queue_length)
|
||||
.def_readonly("failcount", &peer_info::failcount)
|
||||
.def_readonly("downloading_piece_index", &peer_info::downloading_piece_index)
|
||||
.def_readonly("downloading_block_index", &peer_info::downloading_block_index)
|
||||
.add_property("downloading_piece_index", make_getter(&peer_info::downloading_piece_index, by_value()))
|
||||
.add_property("downloading_block_index", make_getter(&peer_info::downloading_block_index, by_value()))
|
||||
.def_readonly("downloading_progress", &peer_info::downloading_progress)
|
||||
.def_readonly("downloading_total", &peer_info::downloading_total)
|
||||
.def_readonly("client", &peer_info::client)
|
||||
|
|
|
@ -341,6 +341,7 @@ void add_piece(torrent_handle& th, piece_index_t piece, char const *data, int fl
|
|||
th.add_piece(piece, data, flags);
|
||||
}
|
||||
|
||||
using by_value = return_value_policy<return_by_value>;
|
||||
void bind_torrent_handle()
|
||||
{
|
||||
// arguments are: number of seconds and tracker index
|
||||
|
@ -473,7 +474,7 @@ void bind_torrent_handle()
|
|||
;
|
||||
|
||||
class_<pool_file_status>("pool_file_status")
|
||||
.def_readonly("file_index", &pool_file_status::file_index)
|
||||
.add_property("file_index", make_getter((&pool_file_status::file_index), by_value()))
|
||||
.def_readonly("last_use", &pool_file_status::last_use)
|
||||
.def_readonly("open_mode", &pool_file_status::open_mode)
|
||||
;
|
||||
|
|
|
@ -208,6 +208,7 @@ std::shared_ptr<torrent_info> bencoded_constructor1(entry const& ent)
|
|||
return bencoded_constructor0(ent, 0);
|
||||
}
|
||||
|
||||
using by_value = return_value_policy<return_by_value>;
|
||||
void bind_torrent_info()
|
||||
{
|
||||
return_value_policy<copy_const_reference> copy;
|
||||
|
@ -218,7 +219,7 @@ void bind_torrent_info()
|
|||
#endif
|
||||
|
||||
class_<file_slice>("file_slice")
|
||||
.def_readwrite("file_index", &file_slice::file_index)
|
||||
.add_property("file_index", make_getter((&file_slice::file_index), by_value()))
|
||||
.def_readwrite("offset", &file_slice::offset)
|
||||
.def_readwrite("size", &file_slice::size)
|
||||
;
|
||||
|
|
|
@ -8,6 +8,13 @@ import time
|
|||
import os
|
||||
import shutil
|
||||
import binascii
|
||||
import subprocess as sub
|
||||
import sys
|
||||
|
||||
# include terminal interface for travis parallel executions of scripts which use
|
||||
# terminal features: fix multiple stdin assignment at termios.tcgetattr
|
||||
if os.name != 'nt':
|
||||
import pty
|
||||
|
||||
|
||||
class test_create_torrent(unittest.TestCase):
|
||||
|
@ -263,6 +270,109 @@ class test_sha1hash(unittest.TestCase):
|
|||
|
||||
class test_session(unittest.TestCase):
|
||||
|
||||
def test_post_session_stats(self):
|
||||
s = lt.session({'alert_mask': lt.alert.category_t.stats_notification, 'enable_dht': False})
|
||||
s.post_session_stats()
|
||||
a = s.wait_for_alert(1000)
|
||||
self.assertTrue(isinstance(a, lt.session_stats_alert))
|
||||
self.assertTrue(isinstance(a.values, dict))
|
||||
self.assertTrue(len(a.values) > 0)
|
||||
|
||||
def test_add_torrent(self):
|
||||
s = lt.session({'alert_mask': lt.alert.category_t.stats_notification, 'enable_dht': False})
|
||||
h = s.add_torrent({'ti': lt.torrent_info('base.torrent'),
|
||||
'save_path': '.',
|
||||
'dht_nodes': [('1.2.3.4', 6881), ('4.3.2.1', 6881)],
|
||||
'http_seeds': ['http://test.com/seed'],
|
||||
'peers': [('5.6.7.8', 6881)],
|
||||
'banned_peers': [('8.7.6.5', 6881)],
|
||||
'file_priorities': [1,1,1,2,0]})
|
||||
|
||||
def test_unknown_settings(self):
|
||||
try:
|
||||
s = lt.session({'unexpected-key-name': 42})
|
||||
self.assertFalse('should have thrown an exception')
|
||||
except KeyError as e:
|
||||
print(e)
|
||||
|
||||
def test_apply_settings(self):
|
||||
|
||||
s = lt.session({'enable_dht': False})
|
||||
s.apply_settings({'num_want': 66, 'user_agent': 'test123'})
|
||||
self.assertEqual(s.get_settings()['num_want'], 66)
|
||||
self.assertEqual(s.get_settings()['user_agent'], 'test123')
|
||||
|
||||
class test_example_client(unittest.TestCase):
|
||||
|
||||
def test_execute_client(self):
|
||||
if os.name == 'nt':
|
||||
# TODO: fix windows includes of client.py
|
||||
return
|
||||
my_stdin = sys.stdin
|
||||
if os.name != 'nt':
|
||||
master_fd, slave_fd = pty.openpty()
|
||||
# slave_fd fix multiple stdin assignment at termios.tcgetattr
|
||||
my_stdin = slave_fd
|
||||
|
||||
process = sub.Popen(
|
||||
[sys.executable,"client.py","url_seed_multi.torrent"],
|
||||
stdin=my_stdin, stdout=sub.PIPE, stderr=sub.PIPE)
|
||||
# python2 has no Popen.wait() timeout
|
||||
time.sleep(5)
|
||||
returncode = process.poll()
|
||||
if returncode == None:
|
||||
# this is an expected use-case
|
||||
process.kill()
|
||||
err = process.stderr.read().decode("utf-8")
|
||||
self.assertEqual('', err, 'process throw errors: \n' + err)
|
||||
# check error code if process did unexpected end
|
||||
if returncode != None:
|
||||
# in case of error return: output stdout if nothing was on stderr
|
||||
if returncode != 0:
|
||||
print("stdout:\n" + process.stdout.read().decode("utf-8"))
|
||||
self.assertEqual(returncode, 0, "returncode: " + str(returncode) + "\n"
|
||||
+ "stderr: empty\n"
|
||||
+ "some configuration does not output errors like missing module members,"
|
||||
+ "try to call it manually to get the error message\n")
|
||||
|
||||
def test_execute_simple_client(self):
|
||||
process = sub.Popen(
|
||||
[sys.executable,"simple_client.py","url_seed_multi.torrent"],
|
||||
stdout=sub.PIPE, stderr=sub.PIPE)
|
||||
# python2 has no Popen.wait() timeout
|
||||
time.sleep(5)
|
||||
returncode = process.poll()
|
||||
if returncode == None:
|
||||
# this is an expected use-case
|
||||
process.kill()
|
||||
err = process.stderr.read().decode("utf-8")
|
||||
self.assertEqual('', err, 'process throw errors: \n' + err)
|
||||
# check error code if process did unexpected end
|
||||
if returncode != None:
|
||||
# in case of error return: output stdout if nothing was on stderr
|
||||
if returncode != 0:
|
||||
print("stdout:\n" + process.stdout.read().decode("utf-8"))
|
||||
self.assertEqual(returncode, 0, "returncode: " + str(returncode) + "\n"
|
||||
+ "stderr: empty\n"
|
||||
+ "some configuration does not output errors like missing module members,"
|
||||
+ "try to call it manually to get the error message\n")
|
||||
|
||||
def test_execute_make_torrent(self):
|
||||
process = sub.Popen(
|
||||
[sys.executable,"make_torrent.py","url_seed_multi.torrent",
|
||||
"http://test.com/test"], stdout=sub.PIPE, stderr=sub.PIPE)
|
||||
returncode = process.wait()
|
||||
# python2 has no Popen.wait() timeout
|
||||
err = process.stderr.read().decode("utf-8")
|
||||
self.assertEqual('', err, 'process throw errors: \n' + err)
|
||||
# in case of error return: output stdout if nothing was on stderr
|
||||
if returncode != 0:
|
||||
print("stdout:\n" + process.stdout.read().decode("utf-8"))
|
||||
self.assertEqual(returncode, 0, "returncode: " + str(returncode) + "\n"
|
||||
+ "stderr: empty\n"
|
||||
+ "some configuration does not output errors like missing module members,"
|
||||
+ "try to call it manually to get the error message\n")
|
||||
|
||||
def test_post_session_stats(self):
|
||||
s = lt.session({'alert_mask': lt.alert.category_t.stats_notification,
|
||||
'enable_dht': False})
|
||||
|
|
Loading…
Reference in New Issue