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.
Files changed (81) hide show
  1. hatch/__init__.py +1 -1
  2. hatch/cli/__init__.py +71 -0
  3. hatch/cli/__main__.py +1035 -0
  4. hatch/cli/cli_env.py +865 -0
  5. hatch/cli/cli_mcp.py +1965 -0
  6. hatch/cli/cli_package.py +566 -0
  7. hatch/cli/cli_system.py +136 -0
  8. hatch/cli/cli_utils.py +1289 -0
  9. hatch/cli_hatch.py +160 -2838
  10. hatch/mcp_host_config/__init__.py +10 -10
  11. hatch/mcp_host_config/adapters/__init__.py +34 -0
  12. hatch/mcp_host_config/adapters/base.py +170 -0
  13. hatch/mcp_host_config/adapters/claude.py +105 -0
  14. hatch/mcp_host_config/adapters/codex.py +104 -0
  15. hatch/mcp_host_config/adapters/cursor.py +83 -0
  16. hatch/mcp_host_config/adapters/gemini.py +75 -0
  17. hatch/mcp_host_config/adapters/kiro.py +78 -0
  18. hatch/mcp_host_config/adapters/lmstudio.py +79 -0
  19. hatch/mcp_host_config/adapters/registry.py +149 -0
  20. hatch/mcp_host_config/adapters/vscode.py +83 -0
  21. hatch/mcp_host_config/backup.py +5 -3
  22. hatch/mcp_host_config/fields.py +126 -0
  23. hatch/mcp_host_config/models.py +161 -456
  24. hatch/mcp_host_config/reporting.py +57 -16
  25. hatch/mcp_host_config/strategies.py +155 -87
  26. hatch/template_generator.py +1 -1
  27. {hatch_xclam-0.7.1.dev3.dist-info → hatch_xclam-0.8.0.dev1.dist-info}/METADATA +3 -2
  28. {hatch_xclam-0.7.1.dev3.dist-info → hatch_xclam-0.8.0.dev1.dist-info}/RECORD +52 -43
  29. {hatch_xclam-0.7.1.dev3.dist-info → hatch_xclam-0.8.0.dev1.dist-info}/WHEEL +1 -1
  30. hatch_xclam-0.8.0.dev1.dist-info/entry_points.txt +2 -0
  31. tests/cli_test_utils.py +280 -0
  32. tests/integration/cli/__init__.py +14 -0
  33. tests/integration/cli/test_cli_reporter_integration.py +2439 -0
  34. tests/integration/mcp/__init__.py +0 -0
  35. tests/integration/mcp/test_adapter_serialization.py +173 -0
  36. tests/regression/cli/__init__.py +16 -0
  37. tests/regression/cli/test_color_logic.py +268 -0
  38. tests/regression/cli/test_consequence_type.py +298 -0
  39. tests/regression/cli/test_error_formatting.py +328 -0
  40. tests/regression/cli/test_result_reporter.py +586 -0
  41. tests/regression/cli/test_table_formatter.py +211 -0
  42. tests/regression/mcp/__init__.py +0 -0
  43. tests/regression/mcp/test_field_filtering.py +162 -0
  44. tests/test_cli_version.py +7 -5
  45. tests/test_data/fixtures/cli_reporter_fixtures.py +184 -0
  46. tests/unit/__init__.py +0 -0
  47. tests/unit/mcp/__init__.py +0 -0
  48. tests/unit/mcp/test_adapter_protocol.py +138 -0
  49. tests/unit/mcp/test_adapter_registry.py +158 -0
  50. tests/unit/mcp/test_config_model.py +146 -0
  51. hatch_xclam-0.7.1.dev3.dist-info/entry_points.txt +0 -2
  52. tests/integration/test_mcp_kiro_integration.py +0 -153
  53. tests/regression/test_mcp_codex_backup_integration.py +0 -162
  54. tests/regression/test_mcp_codex_host_strategy.py +0 -163
  55. tests/regression/test_mcp_codex_model_validation.py +0 -117
  56. tests/regression/test_mcp_kiro_backup_integration.py +0 -241
  57. tests/regression/test_mcp_kiro_cli_integration.py +0 -141
  58. tests/regression/test_mcp_kiro_decorator_registration.py +0 -71
  59. tests/regression/test_mcp_kiro_host_strategy.py +0 -214
  60. tests/regression/test_mcp_kiro_model_validation.py +0 -116
  61. tests/regression/test_mcp_kiro_omni_conversion.py +0 -104
  62. tests/test_mcp_atomic_operations.py +0 -276
  63. tests/test_mcp_backup_integration.py +0 -308
  64. tests/test_mcp_cli_all_host_specific_args.py +0 -496
  65. tests/test_mcp_cli_backup_management.py +0 -295
  66. tests/test_mcp_cli_direct_management.py +0 -456
  67. tests/test_mcp_cli_discovery_listing.py +0 -582
  68. tests/test_mcp_cli_host_config_integration.py +0 -823
  69. tests/test_mcp_cli_package_management.py +0 -360
  70. tests/test_mcp_cli_partial_updates.py +0 -859
  71. tests/test_mcp_environment_integration.py +0 -520
  72. tests/test_mcp_host_config_backup.py +0 -257
  73. tests/test_mcp_host_configuration_manager.py +0 -331
  74. tests/test_mcp_host_registry_decorator.py +0 -348
  75. tests/test_mcp_pydantic_architecture_v4.py +0 -603
  76. tests/test_mcp_server_config_models.py +0 -242
  77. tests/test_mcp_server_config_type_field.py +0 -221
  78. tests/test_mcp_sync_functionality.py +0 -316
  79. tests/test_mcp_user_feedback_reporting.py +0 -359
  80. {hatch_xclam-0.7.1.dev3.dist-info → hatch_xclam-0.8.0.dev1.dist-info}/licenses/LICENSE +0 -0
  81. {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()