diff --git a/pyproject.toml b/pyproject.toml index 418ec7d..521f6f5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ authors = [ dynamic = ["version"] requires-python = "~=3.12" -scripts.syncplay = "syncplay_boot:boot" +scripts.syncplay = "syncplay_boot:bootstrap" dependencies = [ "pyyaml>=6.0.2", diff --git a/src/syncplay_boot/__init__.py b/src/syncplay_boot/__init__.py index 7625e1d..90a10cb 100644 --- a/src/syncplay_boot/__init__.py +++ b/src/syncplay_boot/__init__.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from .boot import boot +from .boot import bootstrap +from .boot import SyncplayOptions + +__all__ = ['bootstrap', 'SyncplayOptions'] diff --git a/src/syncplay_boot/boot.py b/src/syncplay_boot/boot.py index 3bab721..de8e380 100644 --- a/src/syncplay_boot/boot.py +++ b/src/syncplay_boot/boot.py @@ -280,9 +280,11 @@ def sp_convert(opts: SyncplayOptions) -> list[str]: return args -def boot() -> None: - init_opts() - sys.argv = ['syncplay'] + sp_convert(load_opts()) +def bootstrap(opts: SyncplayOptions | None = None) -> None: + if opts is None: + init_opts() + opts = load_opts() + sys.argv = ['syncplay'] + sp_convert(opts) debug_msg('Syncplay startup arguments', sys.argv) from syncplay import ep_server @@ -290,4 +292,4 @@ def boot() -> None: if __name__ == '__main__': - boot() + bootstrap() diff --git a/tests/test_arg_opts.py b/tests/test_arg_opts.py index b1e1abc..491e911 100644 --- a/tests/test_arg_opts.py +++ b/tests/test_arg_opts.py @@ -3,7 +3,7 @@ import sys import pytest -from src import boot +import syncplay_boot.boot as boot @pytest.fixture(autouse=True) diff --git a/tests/test_cfg_opts.py b/tests/test_cfg_opts.py index b4ef000..b12788e 100644 --- a/tests/test_cfg_opts.py +++ b/tests/test_cfg_opts.py @@ -6,7 +6,7 @@ import toml import yaml import pytest import tempfile -from src import boot +import syncplay_boot.boot as boot @pytest.fixture(autouse=True) diff --git a/tests/test_convert.py b/tests/test_convert.py index c57e409..fcd422f 100644 --- a/tests/test_convert.py +++ b/tests/test_convert.py @@ -4,8 +4,8 @@ import os import pytest import tempfile -from src import boot from typing import Callable +import syncplay_boot.boot as boot from unittest.mock import patch, mock_open @@ -65,7 +65,7 @@ def test_password() -> None: assert convert({'password': 'PWD'}) == ['--password', 'PWD'] # custom password -@patch('src.boot.open', new_callable=mock_open) +@patch('syncplay_boot.boot.open', new_callable=mock_open) def test_motd(mock_file) -> None: """ Test motd field of options conversion. @@ -114,7 +114,7 @@ def test_limited_values() -> None: assert convert({'max_chat_message': 500}) == ['--max-chat-message-length', '500'] -@patch('src.boot.open', new_callable=mock_open) +@patch('syncplay_boot.boot.open', new_callable=mock_open) def test_permanent_rooms(mock_file) -> None: """ Test permanent rooms field of options conversion. diff --git a/tests/test_env_opts.py b/tests/test_env_opts.py index 1c122e5..205925c 100644 --- a/tests/test_env_opts.py +++ b/tests/test_env_opts.py @@ -3,7 +3,7 @@ import os import pytest -from src import boot +import syncplay_boot.boot as boot @pytest.fixture(autouse=True) diff --git a/tests/test_init_opts.py b/tests/test_init_opts.py index 0b7ef8f..64980b7 100644 --- a/tests/test_init_opts.py +++ b/tests/test_init_opts.py @@ -1,24 +1,23 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from src import boot from types import GenericAlias from typing import NotRequired -from src.boot import SyncplayOptions +import syncplay_boot.boot as boot def test_options(): """ Verify types and structure of SyncplayOptions and DESC. """ - assert len(SyncplayOptions.__annotations__) == len(boot.DESC) - assert set(SyncplayOptions.__annotations__) == set(boot.DESC) + assert len(boot.SyncplayOptions.__annotations__) == len(boot.DESC) + assert set(boot.SyncplayOptions.__annotations__) == set(boot.DESC) for tag, desc in boot.DESC.values(): assert tag is None or type(tag) is str assert type(desc) is str - for field in SyncplayOptions.__annotations__.values(): + for field in boot.SyncplayOptions.__annotations__.values(): assert field.__origin__ is NotRequired assert len(field.__args__) == 1 diff --git a/tests/test_load_opts.py b/tests/test_load_opts.py index 8ee23fa..9302a5f 100644 --- a/tests/test_load_opts.py +++ b/tests/test_load_opts.py @@ -2,8 +2,8 @@ # -*- coding: utf-8 -*- import pytest -import src.boot as boot from unittest.mock import patch +import syncplay_boot.boot as boot @pytest.fixture(autouse=True) @@ -12,9 +12,9 @@ def init_opts(): yield -@patch('src.boot.load_from_config') -@patch('src.boot.load_from_args') -@patch('src.boot.load_from_env') +@patch('syncplay_boot.boot.load_from_config') +@patch('syncplay_boot.boot.load_from_args') +@patch('syncplay_boot.boot.load_from_env') def test_config_priority(mock_env, mock_arg, mock_cfg) -> None: """ Test configure file loading priority order. @@ -35,9 +35,9 @@ def test_config_priority(mock_env, mock_arg, mock_cfg) -> None: mock_cfg.assert_called_with('arg_config.yml') # higher priority than env -@patch('src.boot.load_from_config') -@patch('src.boot.load_from_args') -@patch('src.boot.load_from_env') +@patch('syncplay_boot.boot.load_from_config') +@patch('syncplay_boot.boot.load_from_args') +@patch('syncplay_boot.boot.load_from_env') def test_merge_priority(mock_env, mock_arg, mock_cfg) -> None: """ Test the merge priority order among env, cli and config options. @@ -89,9 +89,9 @@ def test_merge_priority(mock_env, mock_arg, mock_cfg) -> None: assert boot.load_opts() == expected_opts # cfg < arg -@patch('src.boot.load_from_config') -@patch('src.boot.load_from_args') -@patch('src.boot.load_from_env') +@patch('syncplay_boot.boot.load_from_config') +@patch('syncplay_boot.boot.load_from_args') +@patch('syncplay_boot.boot.load_from_env') def test_bool_options(mock_env, mock_arg, mock_cfg) -> None: """ Test bool options handling and non-bool retention.