From b19b11f76f6dde57f57521ecced30c55414efa3a Mon Sep 17 00:00:00 2001 From: Robert Luttrell Date: Tue, 28 Nov 2023 10:08:32 -0800 Subject: [PATCH] feat: Add system config path for Windows Signed-off-by: Robert Luttrell --- hatch.toml | 2 +- .../_background/frontend_runner.py | 3 - .../configuration/_configuration_manager.py | 41 ++++++---- test/openjd/adaptor_runtime/conftest.py | 7 ++ .../test_configuration_manager.py | 77 ++++++++++++++++--- 5 files changed, 103 insertions(+), 27 deletions(-) diff --git a/hatch.toml b/hatch.toml index fe39c16..3d33071 100644 --- a/hatch.toml +++ b/hatch.toml @@ -6,7 +6,7 @@ pre-install-commands = [ [envs.default.scripts] sync = "pip install -r requirements-testing.txt" test = "pytest --cov-config pyproject.toml {args:test}" -test-windows = "pytest --cov-config pyproject.toml {args:test/openjd/adaptor_runtime/integ/background} --cov-fail-under=44" +test-windows = "pytest --cov-config pyproject.toml {args:test/openjd/adaptor_runtime/integ/background test/openjd/adaptor_runtime/unit/adaptors/configuration/test_configuration_manager.py} --cov-fail-under=44" typing = "mypy {args:src test}" style = [ "ruff {args:.}", diff --git a/src/openjd/adaptor_runtime/_background/frontend_runner.py b/src/openjd/adaptor_runtime/_background/frontend_runner.py index cbc3f3d..577711f 100644 --- a/src/openjd/adaptor_runtime/_background/frontend_runner.py +++ b/src/openjd/adaptor_runtime/_background/frontend_runner.py @@ -111,9 +111,6 @@ def init( shell=False, close_fds=True, start_new_session=True, - stdin=subprocess.DEVNULL, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, ) except Exception as e: _logger.error(f"Failed to initialize backend process: {e}") diff --git a/src/openjd/adaptor_runtime/adaptors/configuration/_configuration_manager.py b/src/openjd/adaptor_runtime/adaptors/configuration/_configuration_manager.py index 2944377..0b45148 100644 --- a/src/openjd/adaptor_runtime/adaptors/configuration/_configuration_manager.py +++ b/src/openjd/adaptor_runtime/adaptors/configuration/_configuration_manager.py @@ -51,20 +51,33 @@ def create_adaptor_configuration_manager( elif isinstance(schema_path, list): schema_paths.extend(schema_path) - system_config_path_map = { - "Linux": posixpath.abspath( - posixpath.join( - posixpath.sep, - "etc", - "openjd", - "adaptors", - adaptor_name, - f"{adaptor_name}.json", - ) - ), - # TODO: Confirm the windows path format - "Windows": f"C:/tmp/{adaptor_name}/{adaptor_name}.json", - } + if OSName.is_posix(): + system_config_path_map = { + "Linux": posixpath.abspath( + posixpath.join( + posixpath.sep, + "etc", + "openjd", + "adaptors", + adaptor_name, + f"{adaptor_name}.json", + ) + ), + } + + elif OSName.is_windows(): + system_config_path_map = { + "Windows": os.path.abspath( + os.path.join( + os.path.sep, + os.environ["PROGRAMDATA"], + "openjd", + "adaptors", + adaptor_name, + f"{adaptor_name}.json", + ) + ), + } user_config_rel_path = os.path.join(".openjd", "adaptors", adaptor_name, f"{adaptor_name}.json") return ConfigurationManager( diff --git a/test/openjd/adaptor_runtime/conftest.py b/test/openjd/adaptor_runtime/conftest.py index 1537e70..b47b327 100644 --- a/test/openjd/adaptor_runtime/conftest.py +++ b/test/openjd/adaptor_runtime/conftest.py @@ -18,6 +18,13 @@ def pytest_collection_modifyitems(items): "integ", "test_integration_entrypoint.py", ), + os.path.join( + os.path.abspath(os.path.dirname(__file__)), + "unit", + "adaptors", + "configuration", + "test_configuration_manager.py", + ), ] skip_marker = pytest.mark.skip(reason="Skipping tests on Windows") for item in items: diff --git a/test/openjd/adaptor_runtime/unit/adaptors/configuration/test_configuration_manager.py b/test/openjd/adaptor_runtime/unit/adaptors/configuration/test_configuration_manager.py index 135260e..6f2e35b 100644 --- a/test/openjd/adaptor_runtime/unit/adaptors/configuration/test_configuration_manager.py +++ b/test/openjd/adaptor_runtime/unit/adaptors/configuration/test_configuration_manager.py @@ -6,10 +6,11 @@ import re from typing import Generator as _Generator from unittest.mock import MagicMock, call, mock_open, patch +import platform import pytest -import openjd.adaptor_runtime._osname as osname +from openjd.adaptor_runtime._osname import OSName from openjd.adaptor_runtime.adaptors.configuration import ( AdaptorConfiguration as _AdaptorConfiguration, Configuration as _Configuration, @@ -127,11 +128,8 @@ def test_create( assert f"Could not write empty configuration to {path}: " in caplog.text -class TestCreateAdaptorConfigurationManager: - """ - Tests for the create_adaptor_configuration_manager function. - """ - +@pytest.mark.skipif(not OSName.is_posix(), reason="Posix-specific tests") +class TestCreateAdaptorConfigurationManagerPosix: def test_creates_config_manager(self): """ This test is fragile as it relies on the hardcoded path formats to adaptor config files. @@ -162,6 +160,54 @@ def test_creates_config_manager(self): os.path.join(_configuration_manager_dir, "_adaptor_configuration.schema.json") ) + +@pytest.mark.skipif(not OSName.is_windows(), reason="Windows-specific tests") +class TestCreateAdaptorConfigurationManagerWindows: + def test_creates_config_manager(self): + """ + This test is fragile as it relies on the hardcoded path formats to adaptor config files. + """ + # GIVEN + adaptor_name = "adaptor" + default_config_path = "/path/to/config" + + # WHEN + result = _create_adaptor_configuration_manager( + _AdaptorConfiguration, + adaptor_name, + default_config_path, + ) + + # THEN + assert result._config_cls == _AdaptorConfiguration + assert result._default_config_path == default_config_path + assert result._system_config_path_map["Windows"] == ( + os.path.abspath( + os.path.join( + os.path.sep, + os.environ["PROGRAMDATA"], + "openjd", + "adaptors", + adaptor_name, + f"{adaptor_name}.json", + ) + ) + ) + assert result._user_config_rel_path == os.path.join( + ".openjd", "adaptors", adaptor_name, f"{adaptor_name}.json" + ) + assert isinstance(result._schema_path, list) + assert len(result._schema_path) == 1 + assert result._schema_path[0] == os.path.abspath( + os.path.join(_configuration_manager_dir, "_adaptor_configuration.schema.json") + ) + + +class TestCreateAdaptorConfigurationManager: + """ + Tests for the create_adaptor_configuration_manager function. + """ + def test_accepts_single_schema(self): # GIVEN adaptor_name = "adaptor" @@ -481,7 +527,7 @@ class TestSystemConfig: Tests for methods that get the system-level configuration """ - @patch.object(osname.platform, "system") + @patch.object(platform, "system") def test_gets_linux_path(self, mock_system: MagicMock): # GIVEN mock_system.return_value = "Linux" @@ -499,7 +545,20 @@ def test_gets_linux_path(self, mock_system: MagicMock): mock_system.assert_called_once() assert result == expected - @patch.object(osname.platform, "system") + @patch.object(platform, "system") + def test_gets_windows_path(self, mock_system: MagicMock): + # GIVEN + mock_system.return_value = "Windows" + expected = "path\\to\\windows\\system\\config" + manager = ConfigurationManagerMock(system_config_path_map={"Windows": expected}) + + # WHEN + result = manager.get_system_config_path() + + # THEN + assert result == expected + + @patch.object(platform, "system") def test_raises_on_nonvalid_os(self, mock_system: MagicMock): """ Validate a NotImplementedError is Raised if the OSName does not resolve. @@ -515,7 +574,7 @@ def test_raises_on_nonvalid_os(self, mock_system: MagicMock): # THEN mock_system.assert_called_once() - @patch.object(osname, "OSName", return_value="unsupported_os") + @patch.object(OSName, "resolve_os_name", return_value="unsupported_os") def test_raises_on_valid_os_not_implemented(self, mock_system: MagicMock): """ Validate a NotImplementedError is Raised if the OSName resolves but is not supported