From 587f6dafe87d743f695ad2f29a978c6e1a6f4656 Mon Sep 17 00:00:00 2001 From: LittleCoinCoin Date: Tue, 26 Aug 2025 10:13:58 +0900 Subject: [PATCH 1/9] chore: fix hatch version pin to `v0.5.1` --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 17359b5..373814d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ dependencies = [ "ollama==0.5.1", "openai==1.97.0", - "hatch @ git+https://github.com/CrackingShells/Hatch.git@feat/dependency-installers" + "hatch @ git+https://github.com/CrackingShells/Hatch.git@v0.5.1" ] [project.scripts] From a1526014dfd9a4dfc97028b967f8abd178279dfc Mon Sep 17 00:00:00 2001 From: LittleCoinCoin Date: Tue, 26 Aug 2025 10:39:03 +0900 Subject: [PATCH 2/9] test: updating the list of mcp commands Commands `mcp:tool:execute`, `mcp:tool:schema`, `mcp:citations`, and `mcp:reset` were commented out of release v0.4.2 of Hatchling for instability. This makes sure that the regression test deoesn't look for them. --- tests/integration_test_command_system.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/integration_test_command_system.py b/tests/integration_test_command_system.py index e461183..8f9ded0 100644 --- a/tests/integration_test_command_system.py +++ b/tests/integration_test_command_system.py @@ -136,11 +136,11 @@ def test_mcp_command_structure(self): 'mcp:tool:info', 'mcp:tool:enable', 'mcp:tool:disable', - 'mcp:tool:execute', - 'mcp:tool:schema', + #'mcp:tool:execute', + #'mcp:tool:schema', 'mcp:health', - 'mcp:citations', - 'mcp:reset' + #'mcp:citations', + #'mcp:reset' ] for cmd_name in expected_commands: From 2beab4ef6df419988ce13674cc0fd19919ac507d Mon Sep 17 00:00:00 2001 From: LittleCoinCoin Date: Tue, 26 Aug 2025 10:42:49 +0900 Subject: [PATCH 3/9] test: add test tag `requires_api_key` The integration tests for OpenAI all require the API key at test setup when creating the LLM provider instance. Hence we must add the appropriate tag for skipping them when no api keys are available (i.e. often during automation). --- tests/integration_test_openai.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/integration_test_openai.py b/tests/integration_test_openai.py index d47f0b5..712db1f 100644 --- a/tests/integration_test_openai.py +++ b/tests/integration_test_openai.py @@ -165,6 +165,7 @@ def tearDown(self): self.loop.close() @integration_test + @requires_api_key def test_provider_registration(self): """Test that OpenAIProvider is properly registered in the provider registry. @@ -238,6 +239,7 @@ def test_health_check_sync(self): self.fail(f"Health check test failed: {e}") @integration_test + @requires_api_key def test_payload_preparation(self): """Test chat payload preparation for API requests. @@ -430,6 +432,7 @@ def test_simple_chat_integration_sync(self): self.fail(f"Simple chat integration test failed: {e}") @integration_test + @requires_api_key def test_api_key_validation(self): """Test that provider validates API key requirement. From f1ab80d7543bc06ad2f64e9b5033c3f54222e8ef Mon Sep 17 00:00:00 2001 From: LittleCoinCoin Date: Tue, 26 Aug 2025 11:02:36 +0900 Subject: [PATCH 4/9] test: fixing tests of LLMProvider interface The methods `hatchling_to_llm_tool_call` and `hatchling_to_provider_tool_result` were added in the previous update, so the tests checking the integrity of the implementation of this interface were failing. We add the expected implementations. --- tests/feature_test_llm_provider_base.py | 34 +++++++++++++++++++++++++ tests/feature_test_provider_registry.py | 17 +++++++++++++ 2 files changed, 51 insertions(+) diff --git a/tests/feature_test_llm_provider_base.py b/tests/feature_test_llm_provider_base.py index d68183f..43a99a1 100644 --- a/tests/feature_test_llm_provider_base.py +++ b/tests/feature_test_llm_provider_base.py @@ -107,6 +107,23 @@ def llm_to_hatchling_tool_call(self, event): def mcp_to_provider_tool(self, tool_info): """Mock implementation of mcp_to_provider_tool.""" return {"type": "function", "function": {"name": tool_info.name}} + + def hatchling_to_llm_tool_call(self, tool_call): + """Mock implementation of hatchling_to_llm_tool_call.""" + return { + "id": tool_call.tool_call_id, + "function": { + "name": tool_call.function_name, + "arguments": tool_call.arguments + } + } + + def hatchling_to_provider_tool_result(self, tool_result): + """Mock implementation of hatchling_to_provider_tool_result.""" + return { + "tool_call_id": tool_result.tool_call_id, + "content": str(tool_result.result) + } # Should be able to instantiate concrete implementation test_settings = test_data.get_test_settings() @@ -164,6 +181,23 @@ def llm_to_hatchling_tool_call(self, event): def mcp_to_provider_tool(self, tool_info): """Mock implementation of mcp_to_provider_tool.""" return {"type": "function", "function": {"name": tool_info.name}} + + def hatchling_to_llm_tool_call(self, tool_call): + """Mock implementation of hatchling_to_llm_tool_call.""" + return { + "id": tool_call.tool_call_id, + "function": { + "name": tool_call.function_name, + "arguments": tool_call.arguments + } + } + + def hatchling_to_provider_tool_result(self, tool_result): + """Mock implementation of hatchling_to_provider_tool_result.""" + return { + "tool_call_id": tool_result.tool_call_id, + "content": str(tool_result.result) + } provider = OllamaProvider({}) self.assertEqual(provider.provider_name, "ollama", diff --git a/tests/feature_test_provider_registry.py b/tests/feature_test_provider_registry.py index a275ae4..1fe82e7 100644 --- a/tests/feature_test_provider_registry.py +++ b/tests/feature_test_provider_registry.py @@ -74,6 +74,23 @@ def llm_to_hatchling_tool_call(self, event): def mcp_to_provider_tool(self, tool_info): """Mock implementation of mcp_to_provider_tool.""" return {"type": "function", "function": {"name": tool_info.name}} + + def hatchling_to_llm_tool_call(self, tool_call): + """Mock implementation of hatchling_to_llm_tool_call.""" + return { + "id": tool_call.tool_call_id, + "function": { + "name": tool_call.function_name, + "arguments": tool_call.arguments + } + } + + def hatchling_to_provider_tool_result(self, tool_result): + """Mock implementation of hatchling_to_provider_tool_result.""" + return { + "tool_call_id": tool_result.tool_call_id, + "content": str(tool_result.result) + } return TestProvider From b4013f6d7b758314d460e4c63d0237ccb37cc346 Mon Sep 17 00:00:00 2001 From: LittleCoinCoin Date: Tue, 26 Aug 2025 12:20:14 +0900 Subject: [PATCH 5/9] test: transitioned regression tests for versioning We were before implementing a custom system to manage versions automatically. We moved to `semantic-release`, so we must adapt the regression tests associated to the versioning system. --- tests/regression_test_versioning.py | 256 ++++++++++++++++------------ 1 file changed, 143 insertions(+), 113 deletions(-) diff --git a/tests/regression_test_versioning.py b/tests/regression_test_versioning.py index 21e3f4b..1579927 100644 --- a/tests/regression_test_versioning.py +++ b/tests/regression_test_versioning.py @@ -1,150 +1,180 @@ """ -Unit tests for the versioning system. +Regression tests for the semantic-release versioning system. -Simple test script to verify the versioning system works correctly. +Tests to verify the semantic-release configuration and integration works correctly. """ import sys import os import unittest +import json +import toml from pathlib import Path -from unittest import mock - -# Add scripts directory to path -script_dir = Path(__file__).parent.parent / "scripts" -sys.path.insert(0, str(script_dir)) # Import test decorators sys.path.insert(0, str(Path(__file__).parent.parent)) from tests.test_decorators import regression_test -from version_manager import VersionManager - -class TestVersionManager(unittest.TestCase): - """Unit tests for VersionManager.""" +class TestSemanticReleaseConfiguration(unittest.TestCase): + """Regression tests for semantic-release configuration.""" def setUp(self): - # Patch file operations in VersionManager to use in-memory dict - self.patcher_open = mock.patch("builtins.open", new_callable=mock.mock_open) - self.mock_open = self.patcher_open.start() - self.addCleanup(self.patcher_open.stop) - self.version_data = { - 'MAJOR': '1', 'MINOR': '2', 'PATCH': '0', - 'DEV_NUMBER': '', 'BUILD_NUMBER': '', 'BRANCH': 'main' - } - # Patch VersionManager methods that read/write files - self.patcher_read = mock.patch.object(VersionManager, 'read_version_file', return_value=self.version_data.copy()) - self.mock_read = self.patcher_read.start() - self.addCleanup(self.patcher_read.stop) - self.patcher_write = mock.patch.object(VersionManager, 'write_version_file') - self.mock_write = self.patcher_write.start() - self.addCleanup(self.patcher_write.stop) - self.patcher_write_simple = mock.patch.object(VersionManager, 'write_simple_version_file') - self.mock_write_simple = self.patcher_write_simple.start() - self.addCleanup(self.patcher_write_simple.stop) - # Patch os.path.exists and Path.exists to always return True - self.patcher_exists = mock.patch("os.path.exists", return_value=True) - self.mock_exists = self.patcher_exists.start() - self.addCleanup(self.patcher_exists.stop) - self.patcher_path_exists = mock.patch("pathlib.Path.exists", return_value=True) - self.mock_path_exists = self.patcher_path_exists.start() - self.addCleanup(self.patcher_path_exists.stop) + """Set up test fixtures.""" + self.project_root = Path(__file__).parent.parent + self.releaserc_path = self.project_root / ".releaserc.json" + self.pyproject_path = self.project_root / "pyproject.toml" + self.package_json_path = self.project_root / "package.json" @regression_test - def test_get_version_string(self): - vm = VersionManager() - version = vm.get_version_string(self.version_data) - self.assertEqual(version, 'v1.2.0') + def test_releaserc_configuration_exists(self): + """Test that .releaserc.json exists and is valid.""" + self.assertTrue(self.releaserc_path.exists(), + ".releaserc.json configuration file should exist") + + with open(self.releaserc_path, 'r') as f: + config = json.load(f) + + # Verify essential configuration + self.assertIn("repositoryUrl", config, + "repositoryUrl should be configured") + self.assertIn("branches", config, + "branches should be configured") + self.assertIn("plugins", config, + "plugins should be configured") @regression_test - def test_feature_branch_creation_from_main(self): - vm = VersionManager() - self.mock_read.return_value = { - 'MAJOR': '1', 'MINOR': '2', 'PATCH': '0', - 'DEV_NUMBER': '', 'BUILD_NUMBER': '', 'BRANCH': 'main' - } - feat_version = vm.update_version_for_branch('feat/test-feature') - self.assertEqual(feat_version, 'v1.3.0.dev0+build0') + def test_branch_configuration(self): + """Test that branch configuration includes main and dev branches.""" + with open(self.releaserc_path, 'r') as f: + config = json.load(f) + + branches = config.get("branches", []) + branch_names = [] + + for branch in branches: + if isinstance(branch, str): + branch_names.append(branch) + elif isinstance(branch, dict) and "name" in branch: + branch_names.append(branch["name"]) + + self.assertIn("main", branch_names, + "main branch should be configured for releases") + self.assertIn("dev", branch_names, + "dev branch should be configured for pre-releases") @regression_test - def test_feature_branch_update_build_increment(self): - vm = VersionManager() - self.mock_read.return_value = { - 'MAJOR': '1', 'MINOR': '3', 'PATCH': '0', - 'DEV_NUMBER': '0', 'BUILD_NUMBER': '0', 'BRANCH': 'feat/test-feature' - } - feat_version2 = vm.update_version_for_branch('feat/test-feature') - self.assertEqual(feat_version2, 'v1.3.0.dev0+build1') + def test_required_plugins_configured(self): + """Test that required semantic-release plugins are configured.""" + with open(self.releaserc_path, 'r') as f: + config = json.load(f) + + plugins = config.get("plugins", []) + plugin_names = [] + + for plugin in plugins: + if isinstance(plugin, str): + plugin_names.append(plugin) + elif isinstance(plugin, list) and len(plugin) > 0: + plugin_names.append(plugin[0]) + + # Essential plugins for semantic-release + required_plugins = [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + "@semantic-release/changelog", + "@semantic-release/git", + "@semantic-release/github" + ] + + for required_plugin in required_plugins: + self.assertIn(required_plugin, plugin_names, + f"Required plugin {required_plugin} should be configured") @regression_test - def test_fix_branch_creation_from_main(self): - vm = VersionManager() - self.mock_read.return_value = { - 'MAJOR': '1', 'MINOR': '2', 'PATCH': '0', - 'DEV_NUMBER': '', 'BUILD_NUMBER': '', 'BRANCH': 'main' - } - fix_version = vm.update_version_for_branch('fix/test-fix') - self.assertEqual(fix_version, 'v1.2.1.dev0+build0') + def test_pyproject_toml_has_version(self): + """Test that pyproject.toml contains a version field.""" + self.assertTrue(self.pyproject_path.exists(), + "pyproject.toml should exist") + + with open(self.pyproject_path, 'r') as f: + config = toml.load(f) + + self.assertIn("project", config, + "project section should exist in pyproject.toml") + self.assertIn("version", config["project"], + "version should be specified in project section") + + version = config["project"]["version"] + self.assertIsInstance(version, str, + "version should be a string") + self.assertTrue(version, + "version should not be empty") @regression_test - def test_fix_branch_update_build_increment(self): - vm = VersionManager() - self.mock_read.return_value = { - 'MAJOR': '1', 'MINOR': '2', 'PATCH': '1', - 'DEV_NUMBER': '0', 'BUILD_NUMBER': '0', 'BRANCH': 'fix/test-fix' - } - fix_version2 = vm.update_version_for_branch('fix/test-fix') - self.assertEqual(fix_version2, 'v1.2.1.dev0+build1') + def test_package_json_has_semantic_release_dependencies(self): + """Test that package.json includes semantic-release dependencies.""" + self.assertTrue(self.package_json_path.exists(), + "package.json should exist for semantic-release") + + with open(self.package_json_path, 'r') as f: + config = json.load(f) + + # Check devDependencies for semantic-release + dev_deps = config.get("devDependencies", {}) + + self.assertIn("semantic-release", dev_deps, + "semantic-release should be in devDependencies") + self.assertIn("@semantic-release/changelog", dev_deps, + "@semantic-release/changelog should be in devDependencies") + self.assertIn("@semantic-release/git", dev_deps, + "@semantic-release/git should be in devDependencies") @regression_test - def test_switching_between_fix_branches_patch_increment(self): - vm = VersionManager() - self.mock_read.return_value = { - 'MAJOR': '1', 'MINOR': '2', 'PATCH': '1', - 'DEV_NUMBER': '0', 'BUILD_NUMBER': '1', 'BRANCH': 'fix/test-fix' - } - fix_version3 = vm.update_version_for_branch('fix/another-fix') - self.assertTrue(fix_version3.startswith('v1.2.2')) - - @regression_test - def test_dev_branch_from_main(self): - vm = VersionManager() - self.mock_read.return_value = { - 'MAJOR': '1', 'MINOR': '2', 'PATCH': '0', - 'DEV_NUMBER': '', 'BUILD_NUMBER': '', 'BRANCH': 'main' - } - dev_version = vm.update_version_for_branch('dev') - self.assertEqual(dev_version, 'v1.3.0.dev0') - - @regression_test - def test_dev_branch_from_feature_increment_dev_number(self): - vm = VersionManager() - self.mock_read.return_value = { - 'MAJOR': '1', 'MINOR': '3', 'PATCH': '0', - 'DEV_NUMBER': '0', 'BUILD_NUMBER': '2', 'BRANCH': 'feat/test-feature' - } - dev_version2 = vm.update_version_for_branch('dev') - self.assertEqual(dev_version2, 'v1.3.0.dev1') - + def test_conventional_commits_configuration(self): + """Test that conventional commits preset is configured.""" + with open(self.releaserc_path, 'r') as f: + config = json.load(f) + + plugins = config.get("plugins", []) + + # Find commit-analyzer plugin configuration + commit_analyzer_config = None + for plugin in plugins: + if isinstance(plugin, list) and len(plugin) >= 2: + if plugin[0] == "@semantic-release/commit-analyzer": + commit_analyzer_config = plugin[1] + break + + self.assertIsNotNone(commit_analyzer_config, + "commit-analyzer should have configuration") + self.assertEqual(commit_analyzer_config.get("preset"), "conventionalcommits", + "commit-analyzer should use conventionalcommits preset") + @regression_test - def test_main_branch_clears_dev_build(self): - vm = VersionManager() - self.mock_read.return_value = { - 'MAJOR': '1', 'MINOR': '3', 'PATCH': '0', - 'DEV_NUMBER': '2', 'BUILD_NUMBER': '1', 'BRANCH': 'dev' - } - main_version = vm.update_version_for_branch('main') - self.assertEqual(main_version, 'v1.3.0') + def test_version_format_is_semantic(self): + """Test that the current version follows semantic versioning format.""" + with open(self.pyproject_path, 'r') as f: + config = toml.load(f) + + version = config["project"]["version"] + + # Basic semantic version regex: MAJOR.MINOR.PATCH with optional pre-release and build + import re + # Use a simpler, well-formed pattern to validate semantic-like versions (covers common valid forms) + semver_pattern = r'^\d+\.\d+\.\d+(?:-[0-9A-Za-z-.]+)?(?:\+[0-9A-Za-z-.]+)?$' + + self.assertTrue(re.match(semver_pattern, version), + f"Version {version} should follow semantic versioning format") def run_regression_tests(): - """Run all regression tests for versioning system. + """Run all regression tests for semantic-release versioning system. Returns: bool: True if all tests passed, False otherwise. """ loader = unittest.TestLoader() suite = unittest.TestSuite() - suite.addTests(loader.loadTestsFromTestCase(TestVersionManager)) + suite.addTests(loader.loadTestsFromTestCase(TestSemanticReleaseConfiguration)) runner = unittest.TextTestRunner(verbosity=2) result = runner.run(suite) return result.wasSuccessful() @@ -152,7 +182,7 @@ def run_regression_tests(): if __name__ == "__main__": success = run_regression_tests() if success: - print("All versioning regression tests passed!") + print("All semantic-release versioning regression tests passed!") else: - print("Some versioning regression tests failed.") + print("Some semantic-release versioning regression tests failed.") exit(0 if success else 1) \ No newline at end of file From 28a409109f0912516c6138681da8fd1a6ae42654 Mon Sep 17 00:00:00 2001 From: LittleCoinCoin Date: Tue, 26 Aug 2025 13:25:45 +0900 Subject: [PATCH 6/9] test: fixed retrieval of api key for a feature test Testing the way an OpenAI provider handles events required an api key. Minor: deleted useless import statements --- .../feature_test_mcp_tool_call_subscriber.py | 24 +++++++++++++++++-- tests/integration_test_openai.py | 2 -- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/tests/feature_test_mcp_tool_call_subscriber.py b/tests/feature_test_mcp_tool_call_subscriber.py index 9146eb1..c3daa66 100644 --- a/tests/feature_test_mcp_tool_call_subscriber.py +++ b/tests/feature_test_mcp_tool_call_subscriber.py @@ -4,16 +4,21 @@ using provider methods directly instead of the registry pattern. """ +import os import sys import logging import unittest import time +from pathlib import Path +from asyncio.log import logger from unittest.mock import MagicMock +from dotenv import load_dotenv from tests.test_decorators import feature_test, requires_api_key +from hatchling.config.openai_settings import OpenAISettings +from hatchling.config.settings import AppSettings from hatchling.core.llm.event_system import Event, EventType - from hatchling.mcp_utils.mcp_tool_execution import MCPToolExecution from hatchling.mcp_utils.mcp_tool_call_subscriber import MCPToolCallSubscriber from hatchling.core.llm.providers.registry import ProviderRegistry @@ -98,8 +103,23 @@ def test_on_event_openai(self): timestamp=time.time() ) + # load the test api key from local .env + # Load environment variables for API key + env_path = Path(__file__).parent / ".env" + if load_dotenv(env_path): + logger.info("Loaded environment variables from .env file") + else: + logger.warning("No .env file found, using system environment variables") + + api_key = os.environ.get('OPENAI_API_KEY') + if not api_key: + logger.warning("OPENAI_API_KEY environment variable not set") + self.skipTest("OpenAI API key is not set. Please set OPENAI_API_KEY environment variable.") + # Use provider to get the strategy - provider = ProviderRegistry.get_provider(ELLMProvider.OPENAI) + openai_settings = OpenAISettings(api_key=api_key, timeout=30.0) + app_settings = AppSettings(openai=openai_settings) + provider = ProviderRegistry.get_provider(ELLMProvider.OPENAI, app_settings) subscriber = MCPToolCallSubscriber(self.mock_tool_execution) subscriber.on_event(first_event) diff --git a/tests/integration_test_openai.py b/tests/integration_test_openai.py index 712db1f..87332c0 100644 --- a/tests/integration_test_openai.py +++ b/tests/integration_test_openai.py @@ -35,7 +35,6 @@ from hatchling.config.openai_settings import OpenAISettings from hatchling.config.settings import AppSettings from hatchling.config.llm_settings import ELLMProvider -from hatchling.mcp_utils.mcp_tool_lifecycle_subscriber import ToolLifecycleSubscriber from hatchling.core.llm.providers.registry import ProviderRegistry from hatchling.mcp_utils.mcp_tool_data import MCPToolInfo, MCPToolStatus, MCPToolStatusReason from hatchling.core.llm.event_system import ( @@ -47,7 +46,6 @@ EventType, Event ) -from hatchling.mcp_utils.mcp_tool_lifecycle_subscriber import ToolLifecycleSubscriber from hatchling.core.llm.providers.openai_provider import OpenAIProvider logger = logging.getLogger("integration_test_openai") From d376dad0d4b7912d79bb3aa17e22f8f4414e09f6 Mon Sep 17 00:00:00 2001 From: LittleCoinCoin Date: Tue, 26 Aug 2025 14:01:00 +0900 Subject: [PATCH 7/9] test: fix import from `toml` to `tomli` `tomli` is the library actually referenced in the dependencies of `Hatchling` instead of `toml`. Hence, trying to run the tests after simply installing `Hatchling` from the `pyproject.toml`'s definition would fail when trying to use `toml` for other setting file load. test: some forgotten `toml` usage --- tests/regression_test_versioning.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/regression_test_versioning.py b/tests/regression_test_versioning.py index 1579927..956e770 100644 --- a/tests/regression_test_versioning.py +++ b/tests/regression_test_versioning.py @@ -8,7 +8,7 @@ import os import unittest import json -import toml +import tomli from pathlib import Path # Import test decorators @@ -97,7 +97,7 @@ def test_pyproject_toml_has_version(self): "pyproject.toml should exist") with open(self.pyproject_path, 'r') as f: - config = toml.load(f) + config = tomli.load(f) self.assertIn("project", config, "project section should exist in pyproject.toml") @@ -154,7 +154,7 @@ def test_conventional_commits_configuration(self): def test_version_format_is_semantic(self): """Test that the current version follows semantic versioning format.""" with open(self.pyproject_path, 'r') as f: - config = toml.load(f) + config = tomli.load(f) version = config["project"]["version"] From 89b6be21291bd7da5b25c095c69634d08b3fc1a5 Mon Sep 17 00:00:00 2001 From: LittleCoinCoin Date: Tue, 26 Aug 2025 14:02:40 +0900 Subject: [PATCH 8/9] ci(test): fix test running command for ci We cannot expect the running ci to have access to LLM API keys for all the tests. There are some protections by default in how the tests are written but, to be sure, we explicitly indicate that we skip these. --- .github/workflows/semantic-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/semantic-release.yml b/.github/workflows/semantic-release.yml index b71aed5..7a5c5fb 100644 --- a/.github/workflows/semantic-release.yml +++ b/.github/workflows/semantic-release.yml @@ -32,7 +32,7 @@ jobs: pip install -e . - name: Run tests - run: python run_tests.py --regression --feature + run: python run_tests.py --regression --feature --skip requires_api_key release: needs: test From 0dfba4eb33faba37b986608ad3b95c20ed2d96c8 Mon Sep 17 00:00:00 2001 From: LittleCoinCoin Date: Tue, 26 Aug 2025 14:16:36 +0900 Subject: [PATCH 9/9] test: fixing expected IO mode for `tomli.load` Expected IO mode is binary. --- tests/regression_test_versioning.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression_test_versioning.py b/tests/regression_test_versioning.py index 956e770..cd2ee96 100644 --- a/tests/regression_test_versioning.py +++ b/tests/regression_test_versioning.py @@ -96,7 +96,7 @@ def test_pyproject_toml_has_version(self): self.assertTrue(self.pyproject_path.exists(), "pyproject.toml should exist") - with open(self.pyproject_path, 'r') as f: + with open(self.pyproject_path, 'rb') as f: config = tomli.load(f) self.assertIn("project", config, @@ -153,7 +153,7 @@ def test_conventional_commits_configuration(self): @regression_test def test_version_format_is_semantic(self): """Test that the current version follows semantic versioning format.""" - with open(self.pyproject_path, 'r') as f: + with open(self.pyproject_path, 'rb') as f: config = tomli.load(f) version = config["project"]["version"]