Merge branch 'dev'

dev
7sDream 2017-06-20 15:42:07 +08:00
commit 29b4caccec
No known key found for this signature in database
GPG Key ID: 72A6D9FCEDDAB75D
3 changed files with 27 additions and 22 deletions

18
test.py
View File

@ -26,24 +26,18 @@ class Test(unittest.TestCase):
def test_parse_correctness(self): def test_parse_correctness(self):
data = parse_torrent_file(self.TEST_FILENAME) data = parse_torrent_file(self.TEST_FILENAME)
self.assertIn(['udp://p4p.arenabg.ch:1337/announce'], self.assertIn(['udp://tracker.publicbt.com:80/announce'],
data['announce-list']) data['announce-list'])
self.assertEqual(data['comment'], self.assertEqual(data['creation date'], 1409254242)
'Torrent downloaded from https://rarbg.to')
self.assertEqual(data['creation date'], 1472762993)
def test_parse_two_times(self): def test_parse_two_times(self):
with open(self.TEST_FILENAME, 'rb') as fp: with open(self.TEST_FILENAME, 'rb') as fp:
parser = TorrentFileParser(fp) parser = TorrentFileParser(fp)
data = parser.parse() data = parser.parse()
self.assertIn(['udp://p4p.arenabg.ch:1337/announce'], self.assertIn(['udp://tracker.publicbt.com:80/announce'],
data['announce-list']) data['announce-list'])
self.assertEqual(data['comment'], self.assertEqual(data['creation date'], 1409254242)
'Torrent downloaded from https://rarbg.to')
self.assertEqual(data['creation date'], 1472762993)
data = parser.parse() data = parser.parse()
self.assertIn(['udp://p4p.arenabg.ch:1337/announce'], self.assertIn(['udp://tracker.publicbt.com:80/announce'],
data['announce-list']) data['announce-list'])
self.assertEqual(data['comment'], self.assertEqual(data['creation date'], 1409254242)
'Torrent downloaded from https://rarbg.to')
self.assertEqual(data['creation date'], 1472762993)

Binary file not shown.

View File

@ -7,9 +7,9 @@ A .torrent file parser for both Python 2 and 3
Usage: Usage:
data = parse_torrent_file(filename) data = parse_torrent_file(filename)
# or # or
with open(filename, 'rb') as f: # the binary mode 'b' is necessary with open(filename, 'rb') as f: # the binary mode 'b' is necessary
data = TorrentFileParser(f).parse() data = TorrentFileParser(f).parse()
""" """
@ -62,7 +62,7 @@ class TorrentFileParser(object):
def __init__(self, fp, use_ordered_dict=False, encoding='utf-8'): def __init__(self, fp, use_ordered_dict=False, encoding='utf-8'):
""" """
:param fp: a **binary** file-like object to parse, :param fp: a **binary** file-like object to parse,
which means need 'b' mode when use built-in open function which means need 'b' mode when use built-in open function
:param encoding: file content encoding, default utf-8 :param encoding: file content encoding, default utf-8
:param use_ordered_dict: Use collections.OrderedDict as dict container :param use_ordered_dict: Use collections.OrderedDict as dict container
@ -126,7 +126,11 @@ class TorrentFileParser(object):
except InvalidTorrentFileException: except InvalidTorrentFileException:
return return
if k == 'pieces': if k == 'pieces':
v = self._pieces() v = self._next_hash()
elif k == 'ed2k':
v = self._next_hash(16, False)
elif k == 'filehash':
v = self._next_hash(20, False)
else: else:
v = self._next_element() v = self._next_element()
if k == 'encoding': if k == 'encoding':
@ -173,14 +177,19 @@ class TorrentFileParser(object):
def __to_hex(v): def __to_hex(v):
return hex(ord(v) if isinstance(v, str) else v)[2:].rjust(2, str(0)) return hex(ord(v) if isinstance(v, str) else v)[2:].rjust(2, str(0))
def _pieces(self): def _next_hash(self, p_len=20, need_list=True):
raw = self._next_string(decode=False) raw = self._next_string(decode=False)
if len(raw) % 20 != 0: if len(raw) % p_len != 0:
raise InvalidTorrentFileException(self._pos) raise InvalidTorrentFileException(self._pos)
return [ res = [
''.join([self.__to_hex(c) for c in h]) ''.join([self.__to_hex(c) for c in h])
for h in (raw[x:x+20] for x in range(0, len(raw), 20)) for h in (raw[x:x+p_len] for x in range(0, len(raw), p_len))
] ]
if len(res) == 0 and not need_list:
return ''
if len(res) == 1 and not need_list:
return res[0]
return res
def _next_end(self): def _next_end(self):
raise InvalidTorrentFileException(self._pos) raise InvalidTorrentFileException(self._pos)
@ -206,7 +215,7 @@ class TorrentFileParser(object):
def parse_torrent_file(filename, use_ordered_dict=False): def parse_torrent_file(filename, use_ordered_dict=False):
""" """
Shortcut function for parse torrent object use TorrentFileParser Shortcut function for parse torrent object use TorrentFileParser
:param string filename: torrent filename :param string filename: torrent filename
:param bool use_ordered_dict: see :any:`TorrentFileParser.__init__` :param bool use_ordered_dict: see :any:`TorrentFileParser.__init__`
:rtype: dict if ``use_ordered_dict`` is false, :rtype: dict if ``use_ordered_dict`` is false,
@ -229,6 +238,8 @@ def __main():
parser.add_argument('--ascii', '-a', action='store_true', default=False, parser.add_argument('--ascii', '-a', action='store_true', default=False,
help='ensure output json use ascii char, ' help='ensure output json use ascii char, '
'escape other char use \\u') 'escape other char use \\u')
parser.add_argument('--coding', '-c', default='utf-8',
help='string encoding, default utf-8')
parser.add_argument('--version', '-v', action='store_true', default=False, parser.add_argument('--version', '-v', action='store_true', default=False,
help='print version and exit') help='print version and exit')
args = parser.parse_args() args = parser.parse_args()
@ -249,7 +260,7 @@ def __main():
exit(1) exit(1)
# noinspection PyUnboundLocalVariable # noinspection PyUnboundLocalVariable
data = TorrentFileParser(target_file, not args.dict).parse() data = TorrentFileParser(target_file, not args.dict, args.coding).parse()
data = json.dumps( data = json.dumps(
data, ensure_ascii=args.ascii, data, ensure_ascii=args.ascii,