kailash 0.9.15__py3-none-any.whl → 0.9.17__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 (33) hide show
  1. kailash/__init__.py +4 -3
  2. kailash/middleware/database/base_models.py +7 -1
  3. kailash/migration/__init__.py +30 -0
  4. kailash/migration/cli.py +340 -0
  5. kailash/migration/compatibility_checker.py +662 -0
  6. kailash/migration/configuration_validator.py +837 -0
  7. kailash/migration/documentation_generator.py +1828 -0
  8. kailash/migration/examples/__init__.py +5 -0
  9. kailash/migration/examples/complete_migration_example.py +692 -0
  10. kailash/migration/migration_assistant.py +715 -0
  11. kailash/migration/performance_comparator.py +760 -0
  12. kailash/migration/regression_detector.py +1141 -0
  13. kailash/migration/tests/__init__.py +6 -0
  14. kailash/migration/tests/test_compatibility_checker.py +403 -0
  15. kailash/migration/tests/test_integration.py +463 -0
  16. kailash/migration/tests/test_migration_assistant.py +397 -0
  17. kailash/migration/tests/test_performance_comparator.py +433 -0
  18. kailash/monitoring/__init__.py +29 -2
  19. kailash/monitoring/asyncsql_metrics.py +275 -0
  20. kailash/nodes/data/async_sql.py +1828 -33
  21. kailash/runtime/local.py +1255 -8
  22. kailash/runtime/monitoring/__init__.py +1 -0
  23. kailash/runtime/monitoring/runtime_monitor.py +780 -0
  24. kailash/runtime/resource_manager.py +3033 -0
  25. kailash/sdk_exceptions.py +21 -0
  26. kailash/workflow/cyclic_runner.py +18 -2
  27. {kailash-0.9.15.dist-info → kailash-0.9.17.dist-info}/METADATA +1 -1
  28. {kailash-0.9.15.dist-info → kailash-0.9.17.dist-info}/RECORD +33 -14
  29. {kailash-0.9.15.dist-info → kailash-0.9.17.dist-info}/WHEEL +0 -0
  30. {kailash-0.9.15.dist-info → kailash-0.9.17.dist-info}/entry_points.txt +0 -0
  31. {kailash-0.9.15.dist-info → kailash-0.9.17.dist-info}/licenses/LICENSE +0 -0
  32. {kailash-0.9.15.dist-info → kailash-0.9.17.dist-info}/licenses/NOTICE +0 -0
  33. {kailash-0.9.15.dist-info → kailash-0.9.17.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,6 @@
1
+ """Test suite for LocalRuntime migration tools.
2
+
3
+ This package contains comprehensive tests for all migration tools and utilities,
4
+ including compatibility checking, migration assistance, performance comparison,
5
+ configuration validation, documentation generation, and regression detection.
6
+ """
@@ -0,0 +1,403 @@
1
+ """Tests for the CompatibilityChecker class."""
2
+
3
+ import tempfile
4
+ import textwrap
5
+ from pathlib import Path
6
+
7
+ import pytest
8
+
9
+ from kailash.migration.compatibility_checker import (
10
+ AnalysisResult,
11
+ CompatibilityChecker,
12
+ CompatibilityIssue,
13
+ IssueSeverity,
14
+ IssueType,
15
+ )
16
+
17
+
18
+ @pytest.fixture
19
+ def checker():
20
+ """Create a CompatibilityChecker instance for testing."""
21
+ return CompatibilityChecker()
22
+
23
+
24
+ @pytest.fixture
25
+ def temp_project_dir():
26
+ """Create a temporary project directory with test files."""
27
+ with tempfile.TemporaryDirectory() as temp_dir:
28
+ temp_path = Path(temp_dir)
29
+
30
+ # Create test Python files
31
+ (temp_path / "main.py").write_text(
32
+ textwrap.dedent(
33
+ """
34
+ from kailash.runtime.local import LocalRuntime
35
+ from kailash.workflow.builder import WorkflowBuilder
36
+
37
+ # Legacy configuration
38
+ runtime = LocalRuntime(
39
+ enable_parallel=True,
40
+ thread_pool_size=10,
41
+ debug_mode=True
42
+ )
43
+
44
+ # Legacy method usage
45
+ workflow = WorkflowBuilder().build()
46
+ runtime.execute_sync(workflow)
47
+ results = runtime.get_results()
48
+ """
49
+ ).strip()
50
+ )
51
+
52
+ (temp_path / "config.py").write_text(
53
+ textwrap.dedent(
54
+ """
55
+ # Configuration with deprecated parameters
56
+ RUNTIME_CONFIG = {
57
+ 'memory_limit': 1024,
58
+ 'timeout': 300,
59
+ 'log_level': 'DEBUG'
60
+ }
61
+
62
+ def get_runtime():
63
+ from kailash.runtime.local import LocalRuntime
64
+ return LocalRuntime(**RUNTIME_CONFIG)
65
+ """
66
+ ).strip()
67
+ )
68
+
69
+ (temp_path / "modern.py").write_text(
70
+ textwrap.dedent(
71
+ """
72
+ from kailash.runtime.local import LocalRuntime
73
+ from kailash.access_control import UserContext
74
+
75
+ # Modern configuration
76
+ user_context = UserContext(user_id="test")
77
+ runtime = LocalRuntime(
78
+ debug=True,
79
+ max_concurrency=10,
80
+ enable_security=True,
81
+ user_context=user_context
82
+ )
83
+ """
84
+ ).strip()
85
+ )
86
+
87
+ # Create subdirectory with test file
88
+ subdir = temp_path / "subdir"
89
+ subdir.mkdir()
90
+ (subdir / "nested.py").write_text(
91
+ textwrap.dedent(
92
+ """
93
+ from kailash.runtime.local import LocalRuntime
94
+
95
+ # More deprecated usage
96
+ runtime = LocalRuntime(
97
+ enable_parallel=False,
98
+ cache_enabled=True
99
+ )
100
+ """
101
+ ).strip()
102
+ )
103
+
104
+ yield temp_path
105
+
106
+
107
+ class TestCompatibilityChecker:
108
+ """Test cases for CompatibilityChecker."""
109
+
110
+ def test_initialization(self, checker):
111
+ """Test CompatibilityChecker initialization."""
112
+ assert checker is not None
113
+ assert isinstance(checker.deprecated_parameters, dict)
114
+ assert isinstance(checker.breaking_changes, dict)
115
+ assert isinstance(checker.parameter_migrations, dict)
116
+ assert isinstance(checker.enterprise_patterns, dict)
117
+
118
+ def test_analyze_codebase(self, checker, temp_project_dir):
119
+ """Test comprehensive codebase analysis."""
120
+ result = checker.analyze_codebase(temp_project_dir)
121
+
122
+ assert isinstance(result, AnalysisResult)
123
+ assert result.total_files_analyzed > 0
124
+ assert len(result.issues) > 0
125
+ assert isinstance(result.summary, dict)
126
+ assert result.migration_complexity in [
127
+ "trivial",
128
+ "low",
129
+ "medium",
130
+ "high",
131
+ "very_high",
132
+ ]
133
+ assert result.estimated_effort_days >= 0
134
+
135
+ def test_deprecated_parameter_detection(self, checker, temp_project_dir):
136
+ """Test detection of deprecated parameters."""
137
+ result = checker.analyze_codebase(temp_project_dir)
138
+
139
+ # Should detect deprecated parameters
140
+ deprecated_issues = [
141
+ issue
142
+ for issue in result.issues
143
+ if issue.issue_type == IssueType.DEPRECATED_PARAMETER
144
+ ]
145
+
146
+ assert len(deprecated_issues) > 0
147
+
148
+ # Check specific deprecated parameters
149
+ deprecated_params = [issue.parameter for issue in deprecated_issues]
150
+ assert any("enable_parallel" in param for param in deprecated_params)
151
+ assert any("thread_pool_size" in param for param in deprecated_params)
152
+
153
+ def test_breaking_change_detection(self, checker, temp_project_dir):
154
+ """Test detection of breaking changes."""
155
+ result = checker.analyze_codebase(temp_project_dir)
156
+
157
+ breaking_issues = [
158
+ issue
159
+ for issue in result.issues
160
+ if issue.breaking_change or issue.issue_type == IssueType.BREAKING_CHANGE
161
+ ]
162
+
163
+ assert len(breaking_issues) > 0
164
+
165
+ # Should detect execute_sync usage
166
+ execute_sync_issues = [
167
+ issue for issue in breaking_issues if "execute_sync" in issue.description
168
+ ]
169
+ assert len(execute_sync_issues) > 0
170
+
171
+ def test_parameter_migration_detection(self, checker, temp_project_dir):
172
+ """Test detection of parameters that need migration."""
173
+ result = checker.analyze_codebase(temp_project_dir)
174
+
175
+ migration_issues = [
176
+ issue
177
+ for issue in result.issues
178
+ if issue.issue_type == IssueType.CONFIGURATION_UPDATE
179
+ ]
180
+
181
+ assert len(migration_issues) > 0
182
+
183
+ def test_enterprise_feature_detection(self, checker, temp_project_dir):
184
+ """Test detection of enterprise features."""
185
+ result = checker.analyze_codebase(temp_project_dir)
186
+
187
+ enterprise_issues = [
188
+ issue
189
+ for issue in result.issues
190
+ if issue.enterprise_feature
191
+ or issue.issue_type == IssueType.ENTERPRISE_UPGRADE
192
+ ]
193
+
194
+ # Modern.py has UserContext which is an enterprise feature
195
+ assert len(enterprise_issues) > 0
196
+
197
+ def test_complexity_assessment(self, checker, temp_project_dir):
198
+ """Test migration complexity assessment."""
199
+ result = checker.analyze_codebase(temp_project_dir)
200
+
201
+ # With deprecated parameters and breaking changes, should not be trivial
202
+ assert result.migration_complexity != "trivial"
203
+ assert result.estimated_effort_days > 0
204
+
205
+ def test_summary_generation(self, checker, temp_project_dir):
206
+ """Test summary statistics generation."""
207
+ result = checker.analyze_codebase(temp_project_dir)
208
+
209
+ assert "total_issues" in result.summary
210
+ assert "critical_issues" in result.summary
211
+ assert "high_issues" in result.summary
212
+ assert "breaking_changes" in result.summary
213
+ assert "automated_fixes" in result.summary
214
+
215
+ # Verify counts make sense
216
+ total = result.summary["total_issues"]
217
+ critical = result.summary["critical_issues"]
218
+ high = result.summary["high_issues"]
219
+ medium = result.summary["medium_issues"]
220
+ low = result.summary["low_issues"]
221
+
222
+ assert total == len(result.issues)
223
+ assert critical + high + medium + low <= total
224
+
225
+ def test_text_report_generation(self, checker, temp_project_dir):
226
+ """Test text format report generation."""
227
+ result = checker.analyze_codebase(temp_project_dir)
228
+ report = checker.generate_report(result, "text")
229
+
230
+ assert isinstance(report, str)
231
+ assert len(report) > 0
232
+ assert "Migration Compatibility Report" in report
233
+ assert "SUMMARY" in report
234
+ assert "ISSUE BREAKDOWN" in report
235
+
236
+ def test_json_report_generation(self, checker, temp_project_dir):
237
+ """Test JSON format report generation."""
238
+ result = checker.analyze_codebase(temp_project_dir)
239
+ report = checker.generate_report(result, "json")
240
+
241
+ assert isinstance(report, str)
242
+
243
+ # Should be valid JSON
244
+ import json
245
+
246
+ data = json.loads(report)
247
+
248
+ assert "summary" in data
249
+ assert "migration_complexity" in data
250
+ assert "issues" in data
251
+ assert isinstance(data["issues"], list)
252
+
253
+ def test_markdown_report_generation(self, checker, temp_project_dir):
254
+ """Test markdown format report generation."""
255
+ result = checker.analyze_codebase(temp_project_dir)
256
+ report = checker.generate_report(result, "markdown")
257
+
258
+ assert isinstance(report, str)
259
+ assert len(report) > 0
260
+ assert "# LocalRuntime Migration Compatibility Report" in report
261
+ assert "## Summary" in report
262
+ assert "| Metric | Value |" in report
263
+
264
+ def test_include_exclude_patterns(self, checker, temp_project_dir):
265
+ """Test file inclusion and exclusion patterns."""
266
+ # Test inclusion patterns
267
+ result_py_only = checker.analyze_codebase(
268
+ temp_project_dir, include_patterns=["*.py"]
269
+ )
270
+
271
+ # Test exclusion patterns
272
+ result_exclude_subdir = checker.analyze_codebase(
273
+ temp_project_dir, exclude_patterns=["subdir"]
274
+ )
275
+
276
+ assert (
277
+ result_py_only.total_files_analyzed
278
+ >= result_exclude_subdir.total_files_analyzed
279
+ )
280
+
281
+ def test_error_handling(self, checker):
282
+ """Test error handling for invalid inputs."""
283
+ # Non-existent directory
284
+ result = checker.analyze_codebase("/non/existent/path")
285
+
286
+ assert result.total_files_analyzed == 0
287
+ assert len(result.issues) == 0
288
+
289
+ def test_syntax_error_handling(self, checker):
290
+ """Test handling of Python files with syntax errors."""
291
+ with tempfile.TemporaryDirectory() as temp_dir:
292
+ temp_path = Path(temp_dir)
293
+
294
+ # Create file with syntax error
295
+ (temp_path / "broken.py").write_text(
296
+ "def broken_function(\n # Missing closing parenthesis"
297
+ )
298
+
299
+ result = checker.analyze_codebase(temp_path)
300
+
301
+ # Should detect the syntax error
302
+ syntax_errors = [
303
+ issue
304
+ for issue in result.issues
305
+ if "syntax error" in issue.description.lower()
306
+ ]
307
+ assert len(syntax_errors) > 0
308
+
309
+ def test_enterprise_opportunities_identification(self, checker, temp_project_dir):
310
+ """Test identification of enterprise upgrade opportunities."""
311
+ result = checker.analyze_codebase(temp_project_dir)
312
+
313
+ # Should identify opportunities based on patterns in the code
314
+ assert len(result.enterprise_opportunities) >= 0
315
+
316
+ if result.enterprise_opportunities:
317
+ # Should be meaningful suggestions
318
+ for opportunity in result.enterprise_opportunities:
319
+ assert isinstance(opportunity, str)
320
+ assert len(opportunity) > 10 # Reasonable description length
321
+
322
+ def test_issue_severity_assignment(self, checker, temp_project_dir):
323
+ """Test proper severity assignment to issues."""
324
+ result = checker.analyze_codebase(temp_project_dir)
325
+
326
+ # Check that issues have appropriate severities
327
+ for issue in result.issues:
328
+ assert issue.severity in [
329
+ IssueSeverity.CRITICAL,
330
+ IssueSeverity.HIGH,
331
+ IssueSeverity.MEDIUM,
332
+ IssueSeverity.LOW,
333
+ IssueSeverity.INFO,
334
+ ]
335
+
336
+ # Breaking changes should be high or critical severity
337
+ if issue.breaking_change:
338
+ assert issue.severity in [IssueSeverity.CRITICAL, IssueSeverity.HIGH]
339
+
340
+ def test_automated_fix_identification(self, checker, temp_project_dir):
341
+ """Test identification of issues that can be automatically fixed."""
342
+ result = checker.analyze_codebase(temp_project_dir)
343
+
344
+ automated_issues = [issue for issue in result.issues if issue.automated_fix]
345
+
346
+ # Should have at least some automated fixes for deprecated parameters
347
+ assert len(automated_issues) > 0
348
+
349
+ # Automated fixes should typically be for configuration/parameter issues
350
+ for issue in automated_issues:
351
+ assert issue.issue_type in [
352
+ IssueType.DEPRECATED_PARAMETER,
353
+ IssueType.CONFIGURATION_UPDATE,
354
+ IssueType.PERFORMANCE_OPTIMIZATION,
355
+ ]
356
+
357
+
358
+ class TestCompatibilityIssue:
359
+ """Test cases for CompatibilityIssue dataclass."""
360
+
361
+ def test_creation(self):
362
+ """Test CompatibilityIssue creation."""
363
+ issue = CompatibilityIssue(
364
+ issue_type=IssueType.DEPRECATED_PARAMETER,
365
+ severity=IssueSeverity.HIGH,
366
+ description="Test issue",
367
+ file_path="/test/file.py",
368
+ line_number=10,
369
+ code_snippet="test = True",
370
+ recommendation="Update parameter",
371
+ migration_effort="low",
372
+ )
373
+
374
+ assert issue.issue_type == IssueType.DEPRECATED_PARAMETER
375
+ assert issue.severity == IssueSeverity.HIGH
376
+ assert issue.description == "Test issue"
377
+ assert issue.file_path == "/test/file.py"
378
+ assert issue.line_number == 10
379
+ assert issue.code_snippet == "test = True"
380
+ assert issue.recommendation == "Update parameter"
381
+ assert issue.migration_effort == "low"
382
+ assert issue.automated_fix is False
383
+ assert issue.breaking_change is False
384
+ assert issue.enterprise_feature is False
385
+
386
+
387
+ class TestAnalysisResult:
388
+ """Test cases for AnalysisResult dataclass."""
389
+
390
+ def test_creation(self):
391
+ """Test AnalysisResult creation."""
392
+ result = AnalysisResult(total_files_analyzed=5)
393
+
394
+ assert result.total_files_analyzed == 5
395
+ assert isinstance(result.issues, list)
396
+ assert isinstance(result.summary, dict)
397
+ assert result.migration_complexity == "unknown"
398
+ assert result.estimated_effort_days == 0.0
399
+ assert isinstance(result.enterprise_opportunities, list)
400
+
401
+
402
+ if __name__ == "__main__":
403
+ pytest.main([__file__])