Skip to content
This repository has been archived by the owner on Aug 19, 2024. It is now read-only.

Commit

Permalink
Removed TDef and DLMngr torrent create methods
Browse files Browse the repository at this point in the history
In favor of torrents.create_torrent_file
  • Loading branch information
qstokkink committed May 15, 2024
1 parent 86060b7 commit 2c8eae2
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 129 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,9 @@ def write(self, filename: Path) -> None:
"""
Write the contents of this config to a file.
"""
self.config["filename"] = str(filename)
self.config.write()
config_obj = cast(ConfigObj, self.config)
config_obj.filename = str(filename)
config_obj.write()

def set_dest_dir(self, path: Path | str) -> None:
"""
Expand Down
13 changes: 0 additions & 13 deletions src/tribler/core/libtorrent/download_manager/download_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
from validate import Validator
from yarl import URL

from tribler.core.libtorrent import torrents
from tribler.core.libtorrent.download_manager.download import Download
from tribler.core.libtorrent.download_manager.download_config import DownloadConfig
from tribler.core.libtorrent.download_manager.download_state import DownloadState, DownloadStatus
Expand All @@ -35,7 +34,6 @@

if TYPE_CHECKING:
from tribler.core.libtorrent.download_manager.dht_health_manager import DHTHealthManager
from tribler.core.libtorrent.torrents import TorrentFileResult
from tribler.tribler_config import TriblerConfigManager

SOCKS5_PROXY_DEF = 2
Expand Down Expand Up @@ -1061,17 +1059,6 @@ def get_checkpoint_dir(self) -> Path:
"""
return self.state_dir / "dlcheckpoints"

@staticmethod
async def create_torrent_file(file_path_list: list[str], params: dict | None = None) -> TorrentFileResult:
"""
Creates a torrent file.
:param file_path_list: files to add in torrent file
:param params: optional parameters for torrent file
"""
return await asyncio.get_event_loop().run_in_executor(None, torrents.create_torrent_file,
file_path_list, params or {})

def get_downloads_by_name(self, torrent_name: str) -> list[Download]:
"""
Get all downloads for which the UTF-8 name equals the given string.
Expand Down
17 changes: 9 additions & 8 deletions src/tribler/core/libtorrent/restapi/create_torrent_endpoint.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
import base64
import json
from pathlib import Path
Expand All @@ -13,6 +14,7 @@
from tribler.core.libtorrent.download_manager.download_config import DownloadConfig
from tribler.core.libtorrent.download_manager.download_manager import DownloadManager
from tribler.core.libtorrent.torrentdef import TorrentDef
from tribler.core.libtorrent.torrents import create_torrent_file
from tribler.core.restapi.rest_endpoint import (
HTTP_BAD_REQUEST,
MAX_REQUEST_SIZE,
Expand Down Expand Up @@ -91,7 +93,7 @@ async def create_torrent(self, request: Request) -> RESTResponse:
params = {}

if parameters.get("files"):
file_path_list = parameters["files"]
file_path_list = [Path(p) for p in parameters["files"]]
else:
return RESTResponse({"error": "files parameter missing"}, status=HTTP_BAD_REQUEST)

Expand All @@ -118,24 +120,23 @@ async def create_torrent(self, request: Request) -> RESTResponse:
params["encoding"] = False
params["piece length"] = 0 # auto

save_path = export_dir / (f"{name}.torrent") if export_dir and export_dir.exists() else None

try:
result = await self.download_manager.create_torrent_file(file_path_list, recursive_bytes(params))
result = await asyncio.get_event_loop().run_in_executor(None, create_torrent_file,
file_path_list, recursive_bytes(params),
save_path)
except (OSError, UnicodeDecodeError, RuntimeError) as e:
self._logger.exception(e)
return return_handled_exception(e)

metainfo_dict = lt.bdecode(result["metainfo"])

if export_dir and export_dir.exists():
save_path = export_dir / (f"{name}.torrent")
with open(save_path, "wb") as fd: # noqa: ASYNC101
fd.write(result["metainfo"])

# Download this torrent if specified
if "download" in request.query and request.query["download"] and request.query["download"] == "1":
download_config = DownloadConfig.from_defaults(self.download_manager.config)
download_config.set_dest_dir(result["base_dir"])
download_config.set_hops(self.download_manager.config.get("libtorrent/download_defaults/number_hops"))
await self.download_manager.start_download(tdef=TorrentDef(metainfo_dict), config=download_config)
await self.download_manager.start_download(save_path, TorrentDef(metainfo_dict), download_config)

return RESTResponse(json.dumps({"torrent": base64.b64encode(result["metainfo"]).decode()}))
24 changes: 0 additions & 24 deletions src/tribler/core/libtorrent/torrentdef.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import libtorrent as lt

from tribler.core.libtorrent.torrent_file_tree import TorrentFileTree
from tribler.core.libtorrent.torrents import create_torrent_file
from tribler.core.libtorrent.trackers import is_valid_url

if TYPE_CHECKING:
Expand Down Expand Up @@ -204,7 +203,6 @@ def __init__(self, metainfo: MetainfoDict | None = None,
self._logger = logging.getLogger(self.__class__.__name__)
self.torrent_parameters: TorrentParameters = cast(TorrentParameters, {})
self.metainfo: MetainfoDict | None = metainfo
self.files_list: list[Path] = []
self.infohash: bytes | None = None
self._torrent_info: lt.torrent_info | None = None

Expand Down Expand Up @@ -365,14 +363,6 @@ def filter_character(char: int) -> str:

return "".join(map(filter_character, name))

def add_content(self, file_path: Path | str) -> None:
"""
Add some content to the torrent file.
:param file_path: The path of the file to add.
"""
self.files_list.append(Path(file_path).absolute())

def set_encoding(self, enc: bytes) -> None:
"""
Set the character encoding for e.g. the 'name' field.
Expand Down Expand Up @@ -515,20 +505,6 @@ def get_name_as_unicode(self) -> str:

return ""

def save(self, torrent_filepath: str | None = None) -> None:
"""
Generate the metainfo and save the torrent file.
:param torrent_filepath: An optional absolute path to where to save the generated .torrent file.
"""
torrent_dict = create_torrent_file(self.files_list, self.torrent_parameters, torrent_filepath=torrent_filepath)
self._torrent_info = None
with suppress(AttributeError):
del self.torrent_file_tree # Remove the cache without retrieving it or checking if it exists (Error)
self.metainfo = lt.bdecode(torrent_dict['metainfo'])
self.copy_metainfo_to_torrent_parameters()
self.infohash = torrent_dict['infohash']

def _get_all_files_as_unicode_with_length(self) -> Generator[tuple[Path, int], None, None]: # noqa: C901, PLR0912
"""
Get a generator for files in the torrent def. No filtering is possible and all tricks are allowed to obtain
Expand Down
11 changes: 6 additions & 5 deletions src/tribler/test_integration/test_anon_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import TYPE_CHECKING, cast
from unittest.mock import Mock

import libtorrent
from ipv8.community import CommunitySettings
from ipv8.keyvault.crypto import default_eccrypto
from ipv8.messaging.anonymization.tunnel import PEER_FLAG_EXIT_BT
Expand All @@ -16,6 +17,7 @@
from tribler.core.libtorrent.download_manager.download_manager import DownloadManager
from tribler.core.libtorrent.download_manager.download_state import DownloadStatus
from tribler.core.libtorrent.torrentdef import TorrentDef, TorrentDefNoMetainfo
from tribler.core.libtorrent.torrents import create_torrent_file
from tribler.core.notifier import Notifier
from tribler.core.socks5.server import Socks5Server
from tribler.core.tunnel.community import TriblerTunnelCommunity, TriblerTunnelSettings
Expand Down Expand Up @@ -176,9 +178,8 @@ async def start_seeding(self) -> bytes:
with open(config.get_dest_dir() / "ubuntu-15.04-desktop-amd64.iso", "wb") as f: # noqa: ASYNC101
f.write(bytes([0] * 524288))

tdef = TorrentDef()
tdef.add_content(config.get_dest_dir() / "ubuntu-15.04-desktop-amd64.iso")
tdef.save()
metainfo = create_torrent_file([config.get_dest_dir() / "ubuntu-15.04-desktop-amd64.iso"], {})["metainfo"]
tdef = TorrentDef(metainfo=libtorrent.bdecode(metainfo))

download = await self.download_manager_seeder.start_download(tdef=tdef, config=config)
await download.wait_for_status(DownloadStatus.SEEDING)
Expand All @@ -193,9 +194,9 @@ async def start_anon_download(self, infohash: bytes) -> Download:

download = await self.download_manager_downloader.start_download(tdef=TorrentDefNoMetainfo(infohash, b"test"),
config=config)
self.overlay(DOWNLOADER).bittorrent_peers[download] = [
self.overlay(DOWNLOADER).bittorrent_peers[download] = {
("127.0.0.1", self.download_manager_seeder.listen_ports[0]["127.0.0.1"])
]
}

return download

Expand Down
7 changes: 4 additions & 3 deletions src/tribler/test_integration/test_hidden_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import TYPE_CHECKING, cast
from unittest.mock import Mock

import libtorrent
from ipv8.community import CommunitySettings
from ipv8.keyvault.crypto import default_eccrypto
from ipv8.messaging.anonymization.tunnel import PEER_FLAG_EXIT_BT
Expand All @@ -17,6 +18,7 @@
from tribler.core.libtorrent.download_manager.download_manager import DownloadManager
from tribler.core.libtorrent.download_manager.download_state import DownloadStatus
from tribler.core.libtorrent.torrentdef import TorrentDef, TorrentDefNoMetainfo
from tribler.core.libtorrent.torrents import create_torrent_file
from tribler.core.notifier import Notifier
from tribler.core.socks5.server import Socks5Server
from tribler.core.tunnel.community import TriblerTunnelCommunity, TriblerTunnelSettings
Expand Down Expand Up @@ -207,9 +209,8 @@ async def start_seeding(self) -> bytes:
with open(config.get_dest_dir() / "ubuntu-15.04-desktop-amd64.iso", "wb") as f: # noqa: ASYNC101
f.write(bytes([0] * 524288))

tdef = TorrentDef()
tdef.add_content(config.get_dest_dir() / "ubuntu-15.04-desktop-amd64.iso")
tdef.save()
metainfo = create_torrent_file([config.get_dest_dir() / "ubuntu-15.04-desktop-amd64.iso"], {})["metainfo"]
tdef = TorrentDef(metainfo=libtorrent.bdecode(metainfo))

download = await self.download_manager_seeder.start_download(tdef=tdef, config=config)
await download.wait_for_status(DownloadStatus.SEEDING)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from configobj import ConfigObj
from ipv8.test.base import TestBase

import tribler.core.libtorrent.restapi.create_torrent_endpoint as ep_module
from tribler.core.libtorrent.download_manager.download_config import SPEC_CONTENT, DownloadConfig
from tribler.core.libtorrent.restapi.create_torrent_endpoint import CreateTorrentEndpoint
from tribler.core.restapi.rest_endpoint import HTTP_BAD_REQUEST, HTTP_INTERNAL_SERVER_ERROR
Expand Down Expand Up @@ -71,9 +72,8 @@ async def test_failure_oserror(self) -> None:
"""
Test if processing a request that leads to an OSError is gracefully reported.
"""
self.download_manager.create_torrent_file = AsyncMock(side_effect=OSError("test"))

response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))]}))
with patch.dict(ep_module.__dict__, {"create_torrent_file": Mock(side_effect=OSError("test"))}):
response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))]}))
response_body_json = await response_to_json(response)

self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status)
Expand All @@ -85,9 +85,9 @@ async def test_failure_unicodedecodeerror(self) -> None:
"""
Test if processing a request that leads to an OSError is gracefully reported.
"""
self.download_manager.create_torrent_file = AsyncMock(side_effect=UnicodeDecodeError("utf-8", b"", 0, 1, "𓀬"))

response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))]}))
with patch.dict(ep_module.__dict__, {"create_torrent_file":
Mock(side_effect=UnicodeDecodeError("utf-8", b"", 0, 1, "𓀬"))}):
response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))]}))
response_body_json = await response_to_json(response)

self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status)
Expand All @@ -98,9 +98,8 @@ async def test_failure_runtimeerror(self) -> None:
"""
Test if processing a request that leads to an RuntimeError is gracefully reported.
"""
self.download_manager.create_torrent_file = AsyncMock(side_effect=RuntimeError("test"))

response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))]}))
with patch.dict(ep_module.__dict__, {"create_torrent_file": Mock(side_effect=RuntimeError("test"))}):
response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))]}))
response_body_json = await response_to_json(response)

self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status)
Expand All @@ -112,12 +111,12 @@ async def test_create_default(self) -> None:
"""
Test if creating a torrent from defaults works.
"""
self.download_manager.create_torrent_file = AsyncMock(return_value={"metainfo": TORRENT_WITH_DIRS_CONTENT})

response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))]}))
mocked_create_torrent_file = Mock(return_value={"metainfo": TORRENT_WITH_DIRS_CONTENT})
with patch.dict(ep_module.__dict__, {"create_torrent_file": mocked_create_torrent_file}):
response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))]}))
response_body_json = await response_to_json(response)

_, call_params = self.download_manager.create_torrent_file.call_args.args
_, call_params, __ = mocked_create_torrent_file.call_args.args

self.assertEqual(200, response.status)
self.assertEqual(TORRENT_WITH_DIRS_CONTENT, base64.b64decode(response_body_json["torrent"]))
Expand All @@ -130,13 +129,13 @@ async def test_create_with_comment(self) -> None:
"""
Test if creating a torrent with a custom comment works.
"""
self.download_manager.create_torrent_file = AsyncMock(return_value={"metainfo": TORRENT_WITH_DIRS_CONTENT})

response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))],
"description": "test"}))
mocked_create_torrent_file = Mock(return_value={"metainfo": TORRENT_WITH_DIRS_CONTENT})
with patch.dict(ep_module.__dict__, {"create_torrent_file": mocked_create_torrent_file}):
response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))],
"description": "test"}))
response_body_json = await response_to_json(response)

_, call_params = self.download_manager.create_torrent_file.call_args.args
_, call_params, __ = mocked_create_torrent_file.call_args.args

self.assertEqual(200, response.status)
self.assertEqual(TORRENT_WITH_DIRS_CONTENT, base64.b64decode(response_body_json["torrent"]))
Expand All @@ -146,14 +145,15 @@ async def test_create_with_trackers(self) -> None:
"""
Test if creating a torrent with custom trackers works.
"""
self.download_manager.create_torrent_file = AsyncMock(return_value={"metainfo": TORRENT_WITH_DIRS_CONTENT})

response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))],
"trackers": ["http://127.0.0.1/announce",
"http://10.0.0.2/announce"]}))
mocked_create_torrent_file = Mock(return_value={"metainfo": TORRENT_WITH_DIRS_CONTENT})
with patch.dict(ep_module.__dict__, {"create_torrent_file": mocked_create_torrent_file}):
response = await self.endpoint.create_torrent(CreateTorrentRequest({
"files": [str(Path(__file__))],
"trackers": ["http://127.0.0.1/announce", "http://10.0.0.2/announce"]
}))
response_body_json = await response_to_json(response)

_, call_params = self.download_manager.create_torrent_file.call_args.args
_, call_params, __ = mocked_create_torrent_file.call_args.args

self.assertEqual(200, response.status)
self.assertEqual(TORRENT_WITH_DIRS_CONTENT, base64.b64decode(response_body_json["torrent"]))
Expand All @@ -164,13 +164,13 @@ async def test_create_with_name(self) -> None:
"""
Test if creating a torrent with a custom name works.
"""
self.download_manager.create_torrent_file = AsyncMock(return_value={"metainfo": TORRENT_WITH_DIRS_CONTENT})

response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))],
"name": "test"}))
mocked_create_torrent_file = Mock(return_value={"metainfo": TORRENT_WITH_DIRS_CONTENT})
with patch.dict(ep_module.__dict__, {"create_torrent_file": mocked_create_torrent_file}):
response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))],
"name": "test"}))
response_body_json = await response_to_json(response)

_, call_params = self.download_manager.create_torrent_file.call_args.args
_, call_params, __ = mocked_create_torrent_file.call_args.args

self.assertEqual(200, response.status)
self.assertEqual(TORRENT_WITH_DIRS_CONTENT, base64.b64decode(response_body_json["torrent"]))
Expand All @@ -181,19 +181,20 @@ async def test_create_and_start(self) -> None:
Test if creating and starting a download works if download is set to 1.
"""
self.download_manager.config = MockTriblerConfigManager()
self.download_manager.create_torrent_file = AsyncMock(return_value={"metainfo": TORRENT_WITH_DIRS_CONTENT,
"base_dir": str(Path(__file__).parent)})
self.download_manager.start_download = AsyncMock()

mocked_create = Mock(return_value={"metainfo": TORRENT_WITH_DIRS_CONTENT,
"base_dir": str(Path(__file__).parent)})
with patch("tribler.core.libtorrent.download_manager.download_config.DownloadConfig.from_defaults",
lambda _: DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))):
lambda _: DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))), patch.dict(ep_module.__dict__,
{"create_torrent_file":
mocked_create}):
response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))],
"download": "1"}))
response_body_json = await response_to_json(response)

call_kwargs = self.download_manager.start_download.call_args.kwargs
_, tdef, __ = self.download_manager.start_download.call_args.args

self.assertEqual(200, response.status)
self.assertEqual(TORRENT_WITH_DIRS_CONTENT, base64.b64decode(response_body_json["torrent"]))
self.assertEqual(b"\xb3\xba\x19\xc93\xda\x95\x84k\xfd\xf7Z\xd0\x8a\x94\x9cl\xea\xc7\xbc",
call_kwargs["tdef"].infohash)
tdef.infohash)
Loading

0 comments on commit 2c8eae2

Please sign in to comment.