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

Commit

Permalink
Merge pull request #7 from qstokkink/upd_default_statedir
Browse files Browse the repository at this point in the history
Various fixes
  • Loading branch information
qstokkink authored Apr 17, 2024
2 parents 9a67e31 + bf9661e commit 47db16b
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ruff.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ jobs:
**/*.py
- name: Run ruff
if: steps.changed-py-files.outputs.any_changed == 'true'
run: ruff check ${{ steps.changed-py-files.outputs.all_changed_files }}
run: ruff check ${{ steps.changed-py-files.outputs.all_changed_files }} --force-exclude
1 change: 1 addition & 0 deletions .ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ exclude = [
"build",
"dist",
"node_modules",
"src/tribler/gui",
"venv",
]

Expand Down
27 changes: 18 additions & 9 deletions src/run_tribler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,30 @@

import argparse
import asyncio
import typing
from pathlib import Path
import encodings.idna # noqa: F401 (https://github.com/pyinstaller/pyinstaller/issues/1113)
import logging.config
import os
import sys

# https://github.com/pyinstaller/pyinstaller/issues/1113
import encodings.idna # pylint: disable=unused-import
import typing
from pathlib import Path

logger = logging.getLogger(__name__)


class Arguments(typing.TypedDict):
"""
The possible command-line arguments to the core process.
"""

torrent: str
core: bool
log_level: str


def parse_args() -> Arguments:
"""
Parse the command-line arguments.
"""
parser = argparse.ArgumentParser(prog='Tribler [Experimental]', description='Run Tribler BitTorrent client')
parser.add_argument('torrent', help='torrent file to download', default='', nargs='?')
parser.add_argument('--core', action="store_true", help="run core process")
Expand All @@ -33,20 +38,24 @@ def get_root_state_directory(requested_path: os.PathLike | None) -> Path:
"""
Get the default application state directory.
"""
root_state_dir = Path(requested_path) if os.path.isabs(requested_path) else Path(os.getcwd(), requested_path)
root_state_dir = (Path(requested_path) if os.path.isabs(requested_path)
else (Path(os.environ.get("APPDATA", "~")) / ".TriblerExperimental").expanduser().absolute())
root_state_dir.mkdir(parents=True, exist_ok=True)
return root_state_dir


def main():
def main() -> None:
"""
The main script entry point for either the GUI or the core process.
"""
asyncio.set_event_loop(asyncio.SelectorEventLoop())

parsed_args = parse_args()
logging.basicConfig(level=getattr(logging, parsed_args["log_level"]), stream=sys.stdout)
logger.info(f'Run Tribler: {parsed_args}')
logger.info("Run Tribler: %s", parsed_args)

root_state_dir = get_root_state_directory(os.environ.get('TSTATEDIR', 'state_directory'))
logger.info(f'Root state dir: {root_state_dir}')
logger.info("Root state dir: %s", root_state_dir)

api_port, api_key = int(os.environ.get('CORE_API_PORT', '-1')), os.environ.get('CORE_API_KEY')

Expand Down
11 changes: 8 additions & 3 deletions src/tribler/core/start_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@

import logging.config
from asyncio import run
from pathlib import Path
from typing import TYPE_CHECKING

from tribler.core.session import Session
from tribler.tribler_config import TriblerConfigManager

if TYPE_CHECKING:
from pathlib import Path

logger = logging.getLogger(__name__)
CONFIG_FILE_NAME = 'triblerd.conf'


async def run_session(config: TriblerConfigManager) -> None:
"""
Start the Session and wait for it to shut itself down.
"""
session = Session(config)
await session.start()
await session.shutdown_event.wait()
Expand All @@ -26,7 +31,7 @@ def run_core(api_port: int, api_key: str | None, state_dir: Path) -> None:
Returns an exit code value, which is non-zero if the Tribler session finished with an error.
"""
logger.info(f'Start tribler core. API port: "{api_port}". API key: "{api_key}". State dir: "{state_dir}".')
logger.info("Start tribler core. API port: %d. API key: %s. State dir: %s.", api_port, api_key, state_dir)

config = TriblerConfigManager(state_dir / "configuration.json")
config.set("state_dir", str(state_dir))
Expand Down
1 change: 1 addition & 0 deletions src/tribler/gui/widgets/tablecontentmodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ def __init__(self, original_query, **kwargs):
self.original_query = original_query
self.remote_results = {}
title = self.format_title()
kwargs["text_filter"] = original_query
super().__init__(channel_info={"name": title}, **kwargs)
self.remote_results_received = False
self.postponed_remote_results = []
Expand Down
82 changes: 74 additions & 8 deletions src/tribler/tribler_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import json
import logging
import os
from json import JSONDecodeError
from os import PathLike
from pathlib import Path
from typing import TypedDict

Expand All @@ -13,6 +13,10 @@


class ApiConfig(TypedDict):
"""
Settings for the API key component.
"""

key: str
http_enabled: bool
http_port: int
Expand All @@ -23,22 +27,42 @@ class ApiConfig(TypedDict):


class ContentDiscoveryCommunityConfig(TypedDict):
"""
Settings for the content discovery component.
"""

enabled: bool


class DHTDiscoveryCommunityConfig(TypedDict):
"""
Settings for the DHT discovery component.
"""

enabled: bool


class KnowledgeCommunityConfig(TypedDict):
"""
Settings for the knowledge component.
"""

enabled: bool


class DatabaseConfig(TypedDict):
"""
Settings for the database component.
"""

enabled: bool


class DownloadDefaultsConfig(TypedDict):
"""
Settings for default downloads, used by libtorrent.
"""

anonymity_enabled: bool
number_hops: int
safeseeding_enabled: bool
Expand All @@ -51,6 +75,10 @@ class DownloadDefaultsConfig(TypedDict):


class LibtorrentConfig(TypedDict):
"""
Settings for the libtorrent component.
"""

socks_listen_ports: list[int]
port: int
proxy_type: int
Expand All @@ -70,26 +98,46 @@ class LibtorrentConfig(TypedDict):


class RendezvousConfig(TypedDict):
"""
Settings for the rendezvous component.
"""

enabled: bool


class TorrentCheckerConfig(TypedDict):
"""
Settings for the torrent checker component.
"""

enabled: bool


class TunnelCommunityConfig(TypedDict):
"""
Settings for the tunnel community component.
"""

enabled: bool
min_circuits: int
max_circuits: int


class UserActivityConfig(TypedDict):
"""
Settings for the user activity component.
"""

enabled: bool
max_query_history: int
health_check_interval: float


class TriblerConfig(TypedDict):
"""
The main Tribler settings and all of its components' sub-settings.
"""

api: ApiConfig

ipv8: dict
Expand Down Expand Up @@ -157,43 +205,58 @@ class TriblerConfig(TypedDict):
"tunnel_community": TunnelCommunityConfig(enabled=True, min_circuits=1, max_circuits=8),
"user_activity": UserActivityConfig(enabled=True, max_query_history=500, health_check_interval=5.0),

"state_dir": ".",
"state_dir": str((Path(os.environ.get("APPDATA", "~")) / ".TriblerExperimental").expanduser().absolute()),
"memory_db": False
}

# Changes to IPv8 default config
DEFAULT_CONFIG["ipv8"]["keys"].append({
'alias': "secondary",
'generation': "curve25519",
'file': "secondary_key.pem"
})
DEFAULT_CONFIG["ipv8"]["overlays"] = [overlay for overlay in DEFAULT_CONFIG["ipv8"]["overlays"]
if overlay["class"] == "DiscoveryCommunity"]
DEFAULT_CONFIG["ipv8"]["working_directory"] = DEFAULT_CONFIG["state_dir"]
for key_entry in DEFAULT_CONFIG["ipv8"]["keys"]:
if "file" in key_entry:
key_entry["file"] = str(Path(DEFAULT_CONFIG["state_dir"]) / key_entry["file"])


class TriblerConfigManager:
"""
A class that interacts with a JSON configuration file.
"""

def __init__(self, config_file: Path = Path("configuration.json")) -> None:
"""
Load a config from a file
Load a config from a file.
"""
super().__init__()
self.config_file = config_file

logger.info(f'Load: {self.config_file}.')
logger.info("Load: %s.", self.config_file)
self.configuration = {}
if config_file.exists():
try:
with open(self.config_file, "r") as f:
with open(self.config_file) as f:
self.configuration = json.load(f)
except JSONDecodeError as e:
except JSONDecodeError:
logger.exception("Failed to load stored configuration. Falling back to defaults!")
if not self.configuration:
self.configuration = DEFAULT_CONFIG

def write(self) -> None:
"""
Write the configuration to disk.
"""
with open(self.config_file, "w") as f:
json.dump(self.configuration, f, indent=4)

def get(self, option: PathLike | str) -> dict | list | str | int | float | bool | None:
def get(self, option: os.PathLike | str) -> dict | list | str | float | bool | None:
"""
Get a config option based on the path-like descriptor.
"""
out = self.configuration
for part in Path(option).parts:
if part in out:
Expand All @@ -206,7 +269,10 @@ def get(self, option: PathLike | str) -> dict | list | str | int | float | bool
break
return out

def set(self, option: PathLike | str, value: dict | list | str | int | float | bool | None) -> None:
def set(self, option: os.PathLike | str, value: dict | list | str | float | bool | None) -> None:
"""
Set a config option value based on the path-like descriptor.
"""
current = self.configuration
for part in Path(option).parts[:-1]:
current = current[part]
Expand Down

0 comments on commit 47db16b

Please sign in to comment.