hatch-xclam 0.7.1.dev3__py3-none-any.whl → 0.8.0.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hatch/__init__.py +1 -1
- hatch/cli/__init__.py +71 -0
- hatch/cli/__main__.py +1035 -0
- hatch/cli/cli_env.py +865 -0
- hatch/cli/cli_mcp.py +1965 -0
- hatch/cli/cli_package.py +566 -0
- hatch/cli/cli_system.py +136 -0
- hatch/cli/cli_utils.py +1289 -0
- hatch/cli_hatch.py +160 -2838
- hatch/mcp_host_config/__init__.py +10 -10
- hatch/mcp_host_config/adapters/__init__.py +34 -0
- hatch/mcp_host_config/adapters/base.py +170 -0
- hatch/mcp_host_config/adapters/claude.py +105 -0
- hatch/mcp_host_config/adapters/codex.py +104 -0
- hatch/mcp_host_config/adapters/cursor.py +83 -0
- hatch/mcp_host_config/adapters/gemini.py +75 -0
- hatch/mcp_host_config/adapters/kiro.py +78 -0
- hatch/mcp_host_config/adapters/lmstudio.py +79 -0
- hatch/mcp_host_config/adapters/registry.py +149 -0
- hatch/mcp_host_config/adapters/vscode.py +83 -0
- hatch/mcp_host_config/backup.py +5 -3
- hatch/mcp_host_config/fields.py +126 -0
- hatch/mcp_host_config/models.py +161 -456
- hatch/mcp_host_config/reporting.py +57 -16
- hatch/mcp_host_config/strategies.py +155 -87
- hatch/template_generator.py +1 -1
- {hatch_xclam-0.7.1.dev3.dist-info → hatch_xclam-0.8.0.dev1.dist-info}/METADATA +3 -2
- {hatch_xclam-0.7.1.dev3.dist-info → hatch_xclam-0.8.0.dev1.dist-info}/RECORD +52 -43
- {hatch_xclam-0.7.1.dev3.dist-info → hatch_xclam-0.8.0.dev1.dist-info}/WHEEL +1 -1
- hatch_xclam-0.8.0.dev1.dist-info/entry_points.txt +2 -0
- tests/cli_test_utils.py +280 -0
- tests/integration/cli/__init__.py +14 -0
- tests/integration/cli/test_cli_reporter_integration.py +2439 -0
- tests/integration/mcp/__init__.py +0 -0
- tests/integration/mcp/test_adapter_serialization.py +173 -0
- tests/regression/cli/__init__.py +16 -0
- tests/regression/cli/test_color_logic.py +268 -0
- tests/regression/cli/test_consequence_type.py +298 -0
- tests/regression/cli/test_error_formatting.py +328 -0
- tests/regression/cli/test_result_reporter.py +586 -0
- tests/regression/cli/test_table_formatter.py +211 -0
- tests/regression/mcp/__init__.py +0 -0
- tests/regression/mcp/test_field_filtering.py +162 -0
- tests/test_cli_version.py +7 -5
- tests/test_data/fixtures/cli_reporter_fixtures.py +184 -0
- tests/unit/__init__.py +0 -0
- tests/unit/mcp/__init__.py +0 -0
- tests/unit/mcp/test_adapter_protocol.py +138 -0
- tests/unit/mcp/test_adapter_registry.py +158 -0
- tests/unit/mcp/test_config_model.py +146 -0
- hatch_xclam-0.7.1.dev3.dist-info/entry_points.txt +0 -2
- tests/integration/test_mcp_kiro_integration.py +0 -153
- tests/regression/test_mcp_codex_backup_integration.py +0 -162
- tests/regression/test_mcp_codex_host_strategy.py +0 -163
- tests/regression/test_mcp_codex_model_validation.py +0 -117
- tests/regression/test_mcp_kiro_backup_integration.py +0 -241
- tests/regression/test_mcp_kiro_cli_integration.py +0 -141
- tests/regression/test_mcp_kiro_decorator_registration.py +0 -71
- tests/regression/test_mcp_kiro_host_strategy.py +0 -214
- tests/regression/test_mcp_kiro_model_validation.py +0 -116
- tests/regression/test_mcp_kiro_omni_conversion.py +0 -104
- tests/test_mcp_atomic_operations.py +0 -276
- tests/test_mcp_backup_integration.py +0 -308
- tests/test_mcp_cli_all_host_specific_args.py +0 -496
- tests/test_mcp_cli_backup_management.py +0 -295
- tests/test_mcp_cli_direct_management.py +0 -456
- tests/test_mcp_cli_discovery_listing.py +0 -582
- tests/test_mcp_cli_host_config_integration.py +0 -823
- tests/test_mcp_cli_package_management.py +0 -360
- tests/test_mcp_cli_partial_updates.py +0 -859
- tests/test_mcp_environment_integration.py +0 -520
- tests/test_mcp_host_config_backup.py +0 -257
- tests/test_mcp_host_configuration_manager.py +0 -331
- tests/test_mcp_host_registry_decorator.py +0 -348
- tests/test_mcp_pydantic_architecture_v4.py +0 -603
- tests/test_mcp_server_config_models.py +0 -242
- tests/test_mcp_server_config_type_field.py +0 -221
- tests/test_mcp_sync_functionality.py +0 -316
- tests/test_mcp_user_feedback_reporting.py +0 -359
- {hatch_xclam-0.7.1.dev3.dist-info → hatch_xclam-0.8.0.dev1.dist-info}/licenses/LICENSE +0 -0
- {hatch_xclam-0.7.1.dev3.dist-info → hatch_xclam-0.8.0.dev1.dist-info}/top_level.txt +0 -0
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Test suite for MCP CLI backup management commands (Phase 3d).
|
|
3
|
-
|
|
4
|
-
This module tests the new MCP backup management functionality:
|
|
5
|
-
- hatch mcp backup restore
|
|
6
|
-
- hatch mcp backup list
|
|
7
|
-
- hatch mcp backup clean
|
|
8
|
-
|
|
9
|
-
Tests cover argument parsing, backup operations, output formatting,
|
|
10
|
-
and error handling scenarios.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
import unittest
|
|
14
|
-
from unittest.mock import patch, MagicMock, ANY
|
|
15
|
-
import sys
|
|
16
|
-
from pathlib import Path
|
|
17
|
-
from datetime import datetime
|
|
18
|
-
|
|
19
|
-
# Add the parent directory to the path to import hatch modules
|
|
20
|
-
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
21
|
-
|
|
22
|
-
from hatch.cli_hatch import (
|
|
23
|
-
main, handle_mcp_backup_restore, handle_mcp_backup_list, handle_mcp_backup_clean
|
|
24
|
-
)
|
|
25
|
-
from hatch.mcp_host_config.models import MCPHostType
|
|
26
|
-
from wobble import regression_test, integration_test
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class TestMCPBackupRestoreCommand(unittest.TestCase):
|
|
30
|
-
"""Test suite for MCP backup restore command."""
|
|
31
|
-
|
|
32
|
-
@regression_test
|
|
33
|
-
def test_backup_restore_argument_parsing(self):
|
|
34
|
-
"""Test argument parsing for 'hatch mcp backup restore' command."""
|
|
35
|
-
test_args = ['hatch', 'mcp', 'backup', 'restore', 'claude-desktop', '--backup-file', 'test.backup']
|
|
36
|
-
|
|
37
|
-
with patch('sys.argv', test_args):
|
|
38
|
-
with patch('hatch.cli_hatch.HatchEnvironmentManager'):
|
|
39
|
-
with patch('hatch.cli_hatch.handle_mcp_backup_restore', return_value=0) as mock_handler:
|
|
40
|
-
try:
|
|
41
|
-
main()
|
|
42
|
-
mock_handler.assert_called_once_with(
|
|
43
|
-
ANY, 'claude-desktop', 'test.backup', False, False
|
|
44
|
-
)
|
|
45
|
-
except SystemExit as e:
|
|
46
|
-
self.assertEqual(e.code, 0)
|
|
47
|
-
|
|
48
|
-
@regression_test
|
|
49
|
-
def test_backup_restore_dry_run_argument(self):
|
|
50
|
-
"""Test dry run argument for backup restore command."""
|
|
51
|
-
test_args = ['hatch', 'mcp', 'backup', 'restore', 'cursor', '--dry-run', '--auto-approve']
|
|
52
|
-
|
|
53
|
-
with patch('sys.argv', test_args):
|
|
54
|
-
with patch('hatch.cli_hatch.HatchEnvironmentManager'):
|
|
55
|
-
with patch('hatch.cli_hatch.handle_mcp_backup_restore', return_value=0) as mock_handler:
|
|
56
|
-
try:
|
|
57
|
-
main()
|
|
58
|
-
mock_handler.assert_called_once_with(
|
|
59
|
-
ANY, 'cursor', None, True, True
|
|
60
|
-
)
|
|
61
|
-
except SystemExit as e:
|
|
62
|
-
self.assertEqual(e.code, 0)
|
|
63
|
-
|
|
64
|
-
@integration_test(scope="component")
|
|
65
|
-
def test_backup_restore_invalid_host(self):
|
|
66
|
-
"""Test backup restore with invalid host type."""
|
|
67
|
-
with patch('hatch.cli_hatch.HatchEnvironmentManager') as mock_env_manager:
|
|
68
|
-
with patch('builtins.print') as mock_print:
|
|
69
|
-
result = handle_mcp_backup_restore(mock_env_manager.return_value, 'invalid-host')
|
|
70
|
-
|
|
71
|
-
self.assertEqual(result, 1)
|
|
72
|
-
|
|
73
|
-
# Verify error message
|
|
74
|
-
print_calls = [call[0][0] for call in mock_print.call_args_list]
|
|
75
|
-
self.assertTrue(any("Error: Invalid host 'invalid-host'" in call for call in print_calls))
|
|
76
|
-
|
|
77
|
-
@integration_test(scope="component")
|
|
78
|
-
def test_backup_restore_no_backups(self):
|
|
79
|
-
"""Test backup restore when no backups exist."""
|
|
80
|
-
with patch('hatch.mcp_host_config.backup.MCPHostConfigBackupManager') as mock_backup_class:
|
|
81
|
-
mock_backup_manager = MagicMock()
|
|
82
|
-
mock_backup_manager._get_latest_backup.return_value = None
|
|
83
|
-
mock_backup_class.return_value = mock_backup_manager
|
|
84
|
-
|
|
85
|
-
with patch('hatch.cli_hatch.HatchEnvironmentManager') as mock_env_manager:
|
|
86
|
-
with patch('builtins.print') as mock_print:
|
|
87
|
-
result = handle_mcp_backup_restore(mock_env_manager.return_value, 'claude-desktop')
|
|
88
|
-
|
|
89
|
-
self.assertEqual(result, 1)
|
|
90
|
-
|
|
91
|
-
# Verify error message
|
|
92
|
-
print_calls = [call[0][0] for call in mock_print.call_args_list]
|
|
93
|
-
self.assertTrue(any("Error: No backups found for host 'claude-desktop'" in call for call in print_calls))
|
|
94
|
-
|
|
95
|
-
@integration_test(scope="component")
|
|
96
|
-
def test_backup_restore_dry_run(self):
|
|
97
|
-
"""Test backup restore dry run functionality."""
|
|
98
|
-
with patch('hatch.mcp_host_config.backup.MCPHostConfigBackupManager') as mock_backup_class:
|
|
99
|
-
mock_backup_manager = MagicMock()
|
|
100
|
-
mock_backup_path = Path("/test/backup.json")
|
|
101
|
-
mock_backup_manager._get_latest_backup.return_value = mock_backup_path
|
|
102
|
-
mock_backup_class.return_value = mock_backup_manager
|
|
103
|
-
|
|
104
|
-
with patch('hatch.cli_hatch.HatchEnvironmentManager') as mock_env_manager:
|
|
105
|
-
with patch('builtins.print') as mock_print:
|
|
106
|
-
result = handle_mcp_backup_restore(mock_env_manager.return_value, 'claude-desktop', dry_run=True)
|
|
107
|
-
|
|
108
|
-
self.assertEqual(result, 0)
|
|
109
|
-
|
|
110
|
-
# Verify dry run output
|
|
111
|
-
print_calls = [call[0][0] for call in mock_print.call_args_list]
|
|
112
|
-
self.assertTrue(any("[DRY RUN] Would restore backup for host 'claude-desktop'" in call for call in print_calls))
|
|
113
|
-
|
|
114
|
-
@integration_test(scope="component")
|
|
115
|
-
def test_backup_restore_successful(self):
|
|
116
|
-
"""Test successful backup restore operation."""
|
|
117
|
-
with patch('hatch.mcp_host_config.backup.MCPHostConfigBackupManager') as mock_backup_class:
|
|
118
|
-
mock_backup_manager = MagicMock()
|
|
119
|
-
mock_backup_path = Path("/test/backup.json")
|
|
120
|
-
mock_backup_manager._get_latest_backup.return_value = mock_backup_path
|
|
121
|
-
mock_backup_manager.restore_backup.return_value = True
|
|
122
|
-
mock_backup_class.return_value = mock_backup_manager
|
|
123
|
-
|
|
124
|
-
with patch('hatch.cli_hatch.request_confirmation', return_value=True):
|
|
125
|
-
with patch('hatch.cli_hatch.HatchEnvironmentManager') as mock_env_manager:
|
|
126
|
-
with patch('builtins.print') as mock_print:
|
|
127
|
-
result = handle_mcp_backup_restore(mock_env_manager.return_value, 'claude-desktop', auto_approve=True)
|
|
128
|
-
|
|
129
|
-
self.assertEqual(result, 0)
|
|
130
|
-
mock_backup_manager.restore_backup.assert_called_once()
|
|
131
|
-
|
|
132
|
-
# Verify success message
|
|
133
|
-
print_calls = [call[0][0] for call in mock_print.call_args_list]
|
|
134
|
-
self.assertTrue(any("[SUCCESS] Successfully restored backup" in call for call in print_calls))
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
class TestMCPBackupListCommand(unittest.TestCase):
|
|
138
|
-
"""Test suite for MCP backup list command."""
|
|
139
|
-
|
|
140
|
-
@regression_test
|
|
141
|
-
def test_backup_list_argument_parsing(self):
|
|
142
|
-
"""Test argument parsing for 'hatch mcp backup list' command."""
|
|
143
|
-
test_args = ['hatch', 'mcp', 'backup', 'list', 'vscode', '--detailed']
|
|
144
|
-
|
|
145
|
-
with patch('sys.argv', test_args):
|
|
146
|
-
with patch('hatch.cli_hatch.HatchEnvironmentManager'):
|
|
147
|
-
with patch('hatch.cli_hatch.handle_mcp_backup_list', return_value=0) as mock_handler:
|
|
148
|
-
try:
|
|
149
|
-
main()
|
|
150
|
-
mock_handler.assert_called_once_with('vscode', True)
|
|
151
|
-
except SystemExit as e:
|
|
152
|
-
self.assertEqual(e.code, 0)
|
|
153
|
-
|
|
154
|
-
@integration_test(scope="component")
|
|
155
|
-
def test_backup_list_invalid_host(self):
|
|
156
|
-
"""Test backup list with invalid host type."""
|
|
157
|
-
with patch('builtins.print') as mock_print:
|
|
158
|
-
result = handle_mcp_backup_list('invalid-host')
|
|
159
|
-
|
|
160
|
-
self.assertEqual(result, 1)
|
|
161
|
-
|
|
162
|
-
# Verify error message
|
|
163
|
-
print_calls = [call[0][0] for call in mock_print.call_args_list]
|
|
164
|
-
self.assertTrue(any("Error: Invalid host 'invalid-host'" in call for call in print_calls))
|
|
165
|
-
|
|
166
|
-
@integration_test(scope="component")
|
|
167
|
-
def test_backup_list_no_backups(self):
|
|
168
|
-
"""Test backup list when no backups exist."""
|
|
169
|
-
with patch('hatch.mcp_host_config.backup.MCPHostConfigBackupManager') as mock_backup_class:
|
|
170
|
-
mock_backup_manager = MagicMock()
|
|
171
|
-
mock_backup_manager.list_backups.return_value = []
|
|
172
|
-
mock_backup_class.return_value = mock_backup_manager
|
|
173
|
-
|
|
174
|
-
with patch('builtins.print') as mock_print:
|
|
175
|
-
result = handle_mcp_backup_list('claude-desktop')
|
|
176
|
-
|
|
177
|
-
self.assertEqual(result, 0)
|
|
178
|
-
|
|
179
|
-
# Verify no backups message
|
|
180
|
-
print_calls = [call[0][0] for call in mock_print.call_args_list]
|
|
181
|
-
self.assertTrue(any("No backups found for host 'claude-desktop'" in call for call in print_calls))
|
|
182
|
-
|
|
183
|
-
@integration_test(scope="component")
|
|
184
|
-
def test_backup_list_detailed_output(self):
|
|
185
|
-
"""Test backup list with detailed output format."""
|
|
186
|
-
from hatch.mcp_host_config.backup import BackupInfo
|
|
187
|
-
|
|
188
|
-
# Create mock backup info with proper attributes
|
|
189
|
-
mock_backup = MagicMock(spec=BackupInfo)
|
|
190
|
-
mock_backup.file_path = MagicMock()
|
|
191
|
-
mock_backup.file_path.name = "mcp.json.claude-desktop.20250922_143000_123456"
|
|
192
|
-
mock_backup.timestamp = datetime(2025, 9, 22, 14, 30, 0)
|
|
193
|
-
mock_backup.file_size = 1024
|
|
194
|
-
mock_backup.age_days = 5
|
|
195
|
-
|
|
196
|
-
with patch('hatch.mcp_host_config.backup.MCPHostConfigBackupManager') as mock_backup_class:
|
|
197
|
-
mock_backup_manager = MagicMock()
|
|
198
|
-
mock_backup_manager.list_backups.return_value = [mock_backup]
|
|
199
|
-
mock_backup_class.return_value = mock_backup_manager
|
|
200
|
-
|
|
201
|
-
with patch('builtins.print') as mock_print:
|
|
202
|
-
result = handle_mcp_backup_list('claude-desktop', detailed=True)
|
|
203
|
-
|
|
204
|
-
self.assertEqual(result, 0)
|
|
205
|
-
|
|
206
|
-
# Verify detailed table output
|
|
207
|
-
print_calls = [call[0][0] for call in mock_print.call_args_list]
|
|
208
|
-
self.assertTrue(any("Backup File" in call for call in print_calls))
|
|
209
|
-
self.assertTrue(any("Created" in call for call in print_calls))
|
|
210
|
-
self.assertTrue(any("Size" in call for call in print_calls))
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
class TestMCPBackupCleanCommand(unittest.TestCase):
|
|
214
|
-
"""Test suite for MCP backup clean command."""
|
|
215
|
-
|
|
216
|
-
@regression_test
|
|
217
|
-
def test_backup_clean_argument_parsing(self):
|
|
218
|
-
"""Test argument parsing for 'hatch mcp backup clean' command."""
|
|
219
|
-
test_args = ['hatch', 'mcp', 'backup', 'clean', 'cursor', '--older-than-days', '30', '--dry-run']
|
|
220
|
-
|
|
221
|
-
with patch('sys.argv', test_args):
|
|
222
|
-
with patch('hatch.cli_hatch.HatchEnvironmentManager'):
|
|
223
|
-
with patch('hatch.cli_hatch.handle_mcp_backup_clean', return_value=0) as mock_handler:
|
|
224
|
-
try:
|
|
225
|
-
main()
|
|
226
|
-
mock_handler.assert_called_once_with('cursor', 30, None, True, False)
|
|
227
|
-
except SystemExit as e:
|
|
228
|
-
self.assertEqual(e.code, 0)
|
|
229
|
-
|
|
230
|
-
@integration_test(scope="component")
|
|
231
|
-
def test_backup_clean_no_criteria(self):
|
|
232
|
-
"""Test backup clean with no cleanup criteria specified."""
|
|
233
|
-
with patch('builtins.print') as mock_print:
|
|
234
|
-
result = handle_mcp_backup_clean('claude-desktop')
|
|
235
|
-
|
|
236
|
-
self.assertEqual(result, 1)
|
|
237
|
-
|
|
238
|
-
# Verify error message
|
|
239
|
-
print_calls = [call[0][0] for call in mock_print.call_args_list]
|
|
240
|
-
self.assertTrue(any("Error: Must specify either --older-than-days or --keep-count" in call for call in print_calls))
|
|
241
|
-
|
|
242
|
-
@integration_test(scope="component")
|
|
243
|
-
def test_backup_clean_dry_run(self):
|
|
244
|
-
"""Test backup clean dry run functionality."""
|
|
245
|
-
from hatch.mcp_host_config.backup import BackupInfo
|
|
246
|
-
|
|
247
|
-
# Create mock backup info with proper attributes
|
|
248
|
-
mock_backup = MagicMock(spec=BackupInfo)
|
|
249
|
-
mock_backup.file_path = Path("/test/old_backup.json")
|
|
250
|
-
mock_backup.age_days = 35
|
|
251
|
-
|
|
252
|
-
with patch('hatch.mcp_host_config.backup.MCPHostConfigBackupManager') as mock_backup_class:
|
|
253
|
-
mock_backup_manager = MagicMock()
|
|
254
|
-
mock_backup_manager.list_backups.return_value = [mock_backup]
|
|
255
|
-
mock_backup_class.return_value = mock_backup_manager
|
|
256
|
-
|
|
257
|
-
with patch('builtins.print') as mock_print:
|
|
258
|
-
result = handle_mcp_backup_clean('claude-desktop', older_than_days=30, dry_run=True)
|
|
259
|
-
|
|
260
|
-
self.assertEqual(result, 0)
|
|
261
|
-
|
|
262
|
-
# Verify dry run output
|
|
263
|
-
print_calls = [call[0][0] for call in mock_print.call_args_list]
|
|
264
|
-
self.assertTrue(any("[DRY RUN] Would clean" in call for call in print_calls))
|
|
265
|
-
|
|
266
|
-
@integration_test(scope="component")
|
|
267
|
-
def test_backup_clean_successful(self):
|
|
268
|
-
"""Test successful backup clean operation."""
|
|
269
|
-
from hatch.mcp_host_config.backup import BackupInfo
|
|
270
|
-
|
|
271
|
-
# Create mock backup with proper attributes
|
|
272
|
-
mock_backup = MagicMock(spec=BackupInfo)
|
|
273
|
-
mock_backup.file_path = Path("/test/backup.json")
|
|
274
|
-
mock_backup.age_days = 35
|
|
275
|
-
|
|
276
|
-
with patch('hatch.mcp_host_config.backup.MCPHostConfigBackupManager') as mock_backup_class:
|
|
277
|
-
mock_backup_manager = MagicMock()
|
|
278
|
-
mock_backup_manager.list_backups.return_value = [mock_backup] # Some backups exist
|
|
279
|
-
mock_backup_manager.clean_backups.return_value = 3 # 3 backups cleaned
|
|
280
|
-
mock_backup_class.return_value = mock_backup_manager
|
|
281
|
-
|
|
282
|
-
with patch('hatch.cli_hatch.request_confirmation', return_value=True):
|
|
283
|
-
with patch('builtins.print') as mock_print:
|
|
284
|
-
result = handle_mcp_backup_clean('claude-desktop', older_than_days=30, auto_approve=True)
|
|
285
|
-
|
|
286
|
-
self.assertEqual(result, 0)
|
|
287
|
-
mock_backup_manager.clean_backups.assert_called_once()
|
|
288
|
-
|
|
289
|
-
# Verify success message
|
|
290
|
-
print_calls = [call[0][0] for call in mock_print.call_args_list]
|
|
291
|
-
self.assertTrue(any("✓ Successfully cleaned 3 backup(s)" in call for call in print_calls))
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
if __name__ == '__main__':
|
|
295
|
-
unittest.main()
|