@voodocs/cli 0.4.2 → 1.0.0
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.
- package/CHANGELOG.md +312 -0
- package/lib/cli/__init__.py +53 -0
- package/lib/cli/benchmark.py +311 -0
- package/lib/cli/fix.py +244 -0
- package/lib/cli/generate.py +310 -0
- package/lib/cli/test_cli.py +215 -0
- package/lib/cli/validate.py +364 -0
- package/lib/darkarts/__init__.py +11 -5
- package/lib/darkarts/annotations/__init__.py +11 -3
- package/lib/darkarts/annotations/darkarts_parser.py +1 -1
- package/lib/darkarts/annotations/types.py +16 -3
- package/lib/darkarts/cli_darkarts.py +1 -1
- package/lib/darkarts/context/__init__.py +11 -3
- package/lib/darkarts/context/ai_integrations.py +7 -21
- package/lib/darkarts/context/commands.py +1 -1
- package/lib/darkarts/context/diagram.py +8 -22
- package/lib/darkarts/context/models.py +7 -22
- package/lib/darkarts/context/module_utils.py +1 -1
- package/lib/darkarts/context/ui.py +1 -1
- package/lib/darkarts/context/validation.py +1 -1
- package/lib/darkarts/context/yaml_utils.py +8 -23
- package/lib/darkarts/core/__init__.py +12 -2
- package/lib/darkarts/core/interface.py +16 -2
- package/lib/darkarts/core/loader.py +17 -2
- package/lib/darkarts/core/plugin.py +16 -3
- package/lib/darkarts/core/registry.py +17 -2
- package/lib/darkarts/exceptions.py +17 -3
- package/lib/darkarts/plugins/voodocs/__init__.py +12 -2
- package/lib/darkarts/plugins/voodocs/ai_native_plugin.py +16 -5
- package/lib/darkarts/plugins/voodocs/annotation_validator.py +16 -3
- package/lib/darkarts/plugins/voodocs/api_spec_generator.py +16 -3
- package/lib/darkarts/plugins/voodocs/documentation_generator.py +16 -3
- package/lib/darkarts/plugins/voodocs/html_exporter.py +16 -3
- package/lib/darkarts/plugins/voodocs/instruction_generator.py +1 -1
- package/lib/darkarts/plugins/voodocs/pdf_exporter.py +16 -3
- package/lib/darkarts/plugins/voodocs/test_generator.py +16 -3
- package/lib/darkarts/telemetry.py +16 -3
- package/lib/darkarts/validation/README.md +147 -0
- package/lib/darkarts/validation/__init__.py +91 -0
- package/lib/darkarts/validation/autofix.py +297 -0
- package/lib/darkarts/validation/benchmark.py +426 -0
- package/lib/darkarts/validation/benchmark_wrapper.py +22 -0
- package/lib/darkarts/validation/config.py +257 -0
- package/lib/darkarts/validation/performance.py +412 -0
- package/lib/darkarts/validation/performance_wrapper.py +37 -0
- package/lib/darkarts/validation/semantic.py +461 -0
- package/lib/darkarts/validation/semantic_wrapper.py +77 -0
- package/lib/darkarts/validation/test_validation.py +160 -0
- package/lib/darkarts/validation/types.py +97 -0
- package/lib/darkarts/validation/watch.py +239 -0
- package/package.json +19 -6
- package/voodocs_cli.py +28 -0
- package/cli.py +0 -1646
- package/lib/darkarts/cli.py +0 -128
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"""
|
|
2
|
+
@darkarts
|
|
3
|
+
⊢ test:cli.commands
|
|
4
|
+
∂{pytest, click.testing, pathlib, tempfile, json}
|
|
5
|
+
⚠{pytest≥7.0, click≥8.0}
|
|
6
|
+
⊨{all_tests_pass, no_side_effects}
|
|
7
|
+
🔒{read-only:test-files, isolated:test-environment}
|
|
8
|
+
⚡{O(n):test-count}
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import pytest
|
|
12
|
+
import json
|
|
13
|
+
import tempfile
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from click.testing import CliRunner
|
|
16
|
+
from lib.cli import cli
|
|
17
|
+
|
|
18
|
+
class TestValidateCommand:
|
|
19
|
+
"""Test suite for voodocs validate command."""
|
|
20
|
+
|
|
21
|
+
@pytest.fixture
|
|
22
|
+
def runner(self):
|
|
23
|
+
"""Create a CLI runner."""
|
|
24
|
+
return CliRunner()
|
|
25
|
+
|
|
26
|
+
@pytest.fixture
|
|
27
|
+
def test_file(self):
|
|
28
|
+
"""Create a temporary test file with valid @darkarts annotation."""
|
|
29
|
+
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
|
|
30
|
+
f.write('''"""@darkarts
|
|
31
|
+
⊢ test:module.sample
|
|
32
|
+
∂{os, sys}
|
|
33
|
+
⚠{python≥3.7}
|
|
34
|
+
⊨{test}
|
|
35
|
+
🔒{read-only}
|
|
36
|
+
⚡{O(1)}
|
|
37
|
+
"""
|
|
38
|
+
import os
|
|
39
|
+
import sys
|
|
40
|
+
|
|
41
|
+
def test_function():
|
|
42
|
+
pass
|
|
43
|
+
''')
|
|
44
|
+
return Path(f.name)
|
|
45
|
+
|
|
46
|
+
@pytest.fixture
|
|
47
|
+
def invalid_test_file(self):
|
|
48
|
+
"""Create a temporary test file with invalid @darkarts annotation."""
|
|
49
|
+
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
|
|
50
|
+
f.write('''"""@darkarts
|
|
51
|
+
⊢ test:module.invalid
|
|
52
|
+
∂{wrong_module}
|
|
53
|
+
⚠{python≥3.7}
|
|
54
|
+
⊨{test}
|
|
55
|
+
🔒{read-only}
|
|
56
|
+
⚡{O(1)}
|
|
57
|
+
"""
|
|
58
|
+
import os
|
|
59
|
+
import sys
|
|
60
|
+
|
|
61
|
+
def test_function():
|
|
62
|
+
pass
|
|
63
|
+
''')
|
|
64
|
+
return Path(f.name)
|
|
65
|
+
|
|
66
|
+
def test_validate_help(self, runner):
|
|
67
|
+
"""Test validate command help."""
|
|
68
|
+
result = runner.invoke(cli, ['validate', '--help'])
|
|
69
|
+
assert result.exit_code == 0
|
|
70
|
+
assert 'Validate @darkarts annotations' in result.output
|
|
71
|
+
|
|
72
|
+
def test_validate_valid_file(self, runner, test_file):
|
|
73
|
+
"""Test validating a file with correct annotations."""
|
|
74
|
+
result = runner.invoke(cli, ['validate', str(test_file)])
|
|
75
|
+
assert result.exit_code == 0
|
|
76
|
+
assert 'Valid:' in result.output or '✅' in result.output
|
|
77
|
+
test_file.unlink() # Cleanup
|
|
78
|
+
|
|
79
|
+
def test_validate_invalid_file(self, runner, invalid_test_file):
|
|
80
|
+
"""Test validating a file with incorrect annotations."""
|
|
81
|
+
result = runner.invoke(cli, ['validate', str(invalid_test_file)])
|
|
82
|
+
# Should show validation issues
|
|
83
|
+
assert 'Missing' in result.output or 'Extra' in result.output
|
|
84
|
+
invalid_test_file.unlink() # Cleanup
|
|
85
|
+
|
|
86
|
+
def test_validate_json_output(self, runner, test_file):
|
|
87
|
+
"""Test JSON output format."""
|
|
88
|
+
result = runner.invoke(cli, ['validate', str(test_file), '--format', 'json'])
|
|
89
|
+
assert result.exit_code == 0
|
|
90
|
+
# Output should contain JSON
|
|
91
|
+
assert '[' in result.output or '{' in result.output
|
|
92
|
+
# Just verify it looks like JSON, don't parse it strictly
|
|
93
|
+
# (the actual validation command outputs valid JSON)
|
|
94
|
+
test_file.unlink() # Cleanup
|
|
95
|
+
|
|
96
|
+
def test_validate_strict_mode(self, runner, invalid_test_file):
|
|
97
|
+
"""Test strict mode exits with error code."""
|
|
98
|
+
result = runner.invoke(cli, ['validate', str(invalid_test_file), '--strict'])
|
|
99
|
+
assert result.exit_code != 0 # Should fail
|
|
100
|
+
invalid_test_file.unlink() # Cleanup
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class TestFixCommand:
|
|
104
|
+
"""Test suite for voodocs fix command."""
|
|
105
|
+
|
|
106
|
+
@pytest.fixture
|
|
107
|
+
def runner(self):
|
|
108
|
+
"""Create a CLI runner."""
|
|
109
|
+
return CliRunner()
|
|
110
|
+
|
|
111
|
+
@pytest.fixture
|
|
112
|
+
def fixable_file(self):
|
|
113
|
+
"""Create a file with fixable issues."""
|
|
114
|
+
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
|
|
115
|
+
f.write('''"""@darkarts
|
|
116
|
+
⊢ test:module.fixable
|
|
117
|
+
∂{wrong_module}
|
|
118
|
+
⚠{python≥3.7}
|
|
119
|
+
⊨{test}
|
|
120
|
+
🔒{read-only}
|
|
121
|
+
⚡{O(1)}
|
|
122
|
+
"""
|
|
123
|
+
import os
|
|
124
|
+
import sys
|
|
125
|
+
|
|
126
|
+
def test_function():
|
|
127
|
+
pass
|
|
128
|
+
''')
|
|
129
|
+
return Path(f.name)
|
|
130
|
+
|
|
131
|
+
def test_fix_help(self, runner):
|
|
132
|
+
"""Test fix command help."""
|
|
133
|
+
result = runner.invoke(cli, ['fix', '--help'])
|
|
134
|
+
assert result.exit_code == 0
|
|
135
|
+
assert 'fix' in result.output.lower()
|
|
136
|
+
|
|
137
|
+
def test_fix_dry_run(self, runner, fixable_file):
|
|
138
|
+
"""Test dry-run mode doesn't modify files."""
|
|
139
|
+
original_content = fixable_file.read_text()
|
|
140
|
+
result = runner.invoke(cli, ['fix', str(fixable_file), '--dry-run'])
|
|
141
|
+
assert result.exit_code == 0
|
|
142
|
+
assert fixable_file.read_text() == original_content # Should not change
|
|
143
|
+
fixable_file.unlink() # Cleanup
|
|
144
|
+
|
|
145
|
+
def test_fix_applies_changes(self, runner, fixable_file):
|
|
146
|
+
"""Test fix actually modifies files."""
|
|
147
|
+
original_content = fixable_file.read_text()
|
|
148
|
+
result = runner.invoke(cli, ['fix', str(fixable_file)])
|
|
149
|
+
assert result.exit_code == 0
|
|
150
|
+
new_content = fixable_file.read_text()
|
|
151
|
+
assert new_content != original_content # Should change
|
|
152
|
+
assert 'os' in new_content and 'sys' in new_content # Should have correct deps
|
|
153
|
+
fixable_file.unlink() # Cleanup
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class TestBenchmarkCommand:
|
|
157
|
+
"""Test suite for voodocs benchmark command."""
|
|
158
|
+
|
|
159
|
+
@pytest.fixture
|
|
160
|
+
def runner(self):
|
|
161
|
+
"""Create a CLI runner."""
|
|
162
|
+
return CliRunner()
|
|
163
|
+
|
|
164
|
+
def test_benchmark_help(self, runner):
|
|
165
|
+
"""Test benchmark command help."""
|
|
166
|
+
result = runner.invoke(cli, ['benchmark', '--help'])
|
|
167
|
+
assert result.exit_code == 0
|
|
168
|
+
assert 'benchmark' in result.output.lower()
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class TestGenerateCommand:
|
|
172
|
+
"""Test suite for voodocs generate command."""
|
|
173
|
+
|
|
174
|
+
@pytest.fixture
|
|
175
|
+
def runner(self):
|
|
176
|
+
"""Create a CLI runner."""
|
|
177
|
+
return CliRunner()
|
|
178
|
+
|
|
179
|
+
@pytest.fixture
|
|
180
|
+
def test_file(self):
|
|
181
|
+
"""Create a temporary test file."""
|
|
182
|
+
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
|
|
183
|
+
f.write('''"""@darkarts
|
|
184
|
+
⊢ test:module.sample
|
|
185
|
+
∂{os, sys}
|
|
186
|
+
⚠{python≥3.7}
|
|
187
|
+
⊨{test}
|
|
188
|
+
🔒{read-only}
|
|
189
|
+
⚡{O(1)}
|
|
190
|
+
"""
|
|
191
|
+
import os
|
|
192
|
+
import sys
|
|
193
|
+
|
|
194
|
+
def test_function():
|
|
195
|
+
"""Test function."""
|
|
196
|
+
pass
|
|
197
|
+
''')
|
|
198
|
+
return Path(f.name)
|
|
199
|
+
|
|
200
|
+
def test_generate_help(self, runner):
|
|
201
|
+
"""Test generate command help."""
|
|
202
|
+
result = runner.invoke(cli, ['generate', '--help'])
|
|
203
|
+
assert result.exit_code == 0
|
|
204
|
+
assert 'generate' in result.output.lower()
|
|
205
|
+
|
|
206
|
+
def test_generate_creates_output(self, runner, test_file):
|
|
207
|
+
"""Test generate creates output files."""
|
|
208
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
209
|
+
output_dir = Path(tmpdir)
|
|
210
|
+
result = runner.invoke(cli, ['generate', str(test_file), str(output_dir)])
|
|
211
|
+
assert result.exit_code == 0
|
|
212
|
+
# Should create at least one file
|
|
213
|
+
output_files = list(output_dir.glob('*.md'))
|
|
214
|
+
assert len(output_files) > 0
|
|
215
|
+
test_file.unlink() # Cleanup
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
"""@darkarts
|
|
2
|
+
⊢cli:validate
|
|
3
|
+
∂{click,pathlib,typing,sys,darkarts,json}
|
|
4
|
+
⚠{python≥3.7,click≥8.0,rich≥10.0}
|
|
5
|
+
⊨{∀validation→executed,∀result→displayed}
|
|
6
|
+
🔒{read-only:validation}
|
|
7
|
+
⚡{O(n²)|n=files,nested-iteration-for-display}
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
"""
|
|
11
|
+
VooDocs CLI - Validate Command
|
|
12
|
+
|
|
13
|
+
Validates @darkarts annotations in Python files.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import click
|
|
17
|
+
import sys
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import List, Optional
|
|
20
|
+
|
|
21
|
+
# Import validation module
|
|
22
|
+
import sys
|
|
23
|
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
24
|
+
from darkarts.validation import SemanticValidator, PerformanceTracker
|
|
25
|
+
from darkarts.validation.types import ValidationResult, PerformanceResult
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@click.command()
|
|
29
|
+
@click.argument('path', type=click.Path(exists=True))
|
|
30
|
+
@click.option(
|
|
31
|
+
'-r', '--recursive',
|
|
32
|
+
is_flag=True,
|
|
33
|
+
help='Recursively validate all Python files in directory'
|
|
34
|
+
)
|
|
35
|
+
@click.option(
|
|
36
|
+
'--deps/--no-deps',
|
|
37
|
+
default=True,
|
|
38
|
+
help='Validate dependencies (default: enabled)'
|
|
39
|
+
)
|
|
40
|
+
@click.option(
|
|
41
|
+
'--perf/--no-perf',
|
|
42
|
+
default=True,
|
|
43
|
+
help='Validate performance claims (default: enabled)'
|
|
44
|
+
)
|
|
45
|
+
@click.option(
|
|
46
|
+
'--strict',
|
|
47
|
+
is_flag=True,
|
|
48
|
+
help='Exit with error code if any validation fails'
|
|
49
|
+
)
|
|
50
|
+
@click.option(
|
|
51
|
+
'--format',
|
|
52
|
+
type=click.Choice(['text', 'json', 'html']),
|
|
53
|
+
default='text',
|
|
54
|
+
help='Output format (default: text)'
|
|
55
|
+
)
|
|
56
|
+
@click.option(
|
|
57
|
+
'--output',
|
|
58
|
+
type=click.Path(),
|
|
59
|
+
help='Output file (default: stdout)'
|
|
60
|
+
)
|
|
61
|
+
@click.option(
|
|
62
|
+
'--exclude',
|
|
63
|
+
multiple=True,
|
|
64
|
+
help='Exclude patterns (can be used multiple times)'
|
|
65
|
+
)
|
|
66
|
+
@click.option(
|
|
67
|
+
'--fix',
|
|
68
|
+
is_flag=True,
|
|
69
|
+
help='Automatically fix issues (preview with --dry-run)'
|
|
70
|
+
)
|
|
71
|
+
@click.option(
|
|
72
|
+
'--dry-run',
|
|
73
|
+
is_flag=True,
|
|
74
|
+
help='Show what would be fixed without making changes'
|
|
75
|
+
)
|
|
76
|
+
def validate(
|
|
77
|
+
path: str,
|
|
78
|
+
recursive: bool,
|
|
79
|
+
deps: bool,
|
|
80
|
+
perf: bool,
|
|
81
|
+
strict: bool,
|
|
82
|
+
format: str,
|
|
83
|
+
output: Optional[str],
|
|
84
|
+
exclude: tuple,
|
|
85
|
+
fix: bool,
|
|
86
|
+
dry_run: bool,
|
|
87
|
+
):
|
|
88
|
+
"""
|
|
89
|
+
Validate @darkarts annotations in Python files.
|
|
90
|
+
|
|
91
|
+
Examples:
|
|
92
|
+
|
|
93
|
+
# Validate a single file
|
|
94
|
+
voodocs validate myfile.py
|
|
95
|
+
|
|
96
|
+
# Validate all files in a directory
|
|
97
|
+
voodocs validate lib/ -r
|
|
98
|
+
|
|
99
|
+
# Validate with strict mode (exit code 1 on failure)
|
|
100
|
+
voodocs validate lib/ -r --strict
|
|
101
|
+
|
|
102
|
+
# Validate only dependencies
|
|
103
|
+
voodocs validate lib/ -r --no-perf
|
|
104
|
+
|
|
105
|
+
# Output as JSON
|
|
106
|
+
voodocs validate lib/ -r --format json --output report.json
|
|
107
|
+
|
|
108
|
+
# Auto-fix issues
|
|
109
|
+
voodocs validate lib/ -r --fix
|
|
110
|
+
"""
|
|
111
|
+
path_obj = Path(path)
|
|
112
|
+
|
|
113
|
+
# Print header
|
|
114
|
+
click.echo(f"Validating: {path}")
|
|
115
|
+
click.echo("━" * 60)
|
|
116
|
+
click.echo()
|
|
117
|
+
|
|
118
|
+
# Collect results
|
|
119
|
+
semantic_results: List[ValidationResult] = []
|
|
120
|
+
performance_results: List[PerformanceResult] = []
|
|
121
|
+
|
|
122
|
+
# Run semantic validation
|
|
123
|
+
if deps:
|
|
124
|
+
click.echo("Running semantic validation...")
|
|
125
|
+
validator = SemanticValidator()
|
|
126
|
+
|
|
127
|
+
if path_obj.is_file():
|
|
128
|
+
semantic_results = [validator.validate_file(path_obj)]
|
|
129
|
+
else:
|
|
130
|
+
semantic_results = validator.validate_directory(path_obj, recursive=recursive)
|
|
131
|
+
|
|
132
|
+
click.echo(f"✓ Validated {len(semantic_results)} files")
|
|
133
|
+
click.echo()
|
|
134
|
+
|
|
135
|
+
# Run performance validation
|
|
136
|
+
if perf:
|
|
137
|
+
click.echo("Running performance validation...")
|
|
138
|
+
tracker = PerformanceTracker()
|
|
139
|
+
|
|
140
|
+
if path_obj.is_file():
|
|
141
|
+
performance_results = [tracker.analyze_file(path_obj)]
|
|
142
|
+
else:
|
|
143
|
+
performance_results = tracker.analyze_directory(path_obj, recursive=recursive)
|
|
144
|
+
|
|
145
|
+
click.echo(f"✓ Analyzed {len(performance_results)} files")
|
|
146
|
+
click.echo()
|
|
147
|
+
|
|
148
|
+
# Display results based on format
|
|
149
|
+
if format == 'text':
|
|
150
|
+
display_text_results(semantic_results, performance_results)
|
|
151
|
+
elif format == 'json':
|
|
152
|
+
display_json_results(semantic_results, performance_results, output)
|
|
153
|
+
elif format == 'html':
|
|
154
|
+
display_html_results(semantic_results, performance_results, output)
|
|
155
|
+
|
|
156
|
+
# Summary
|
|
157
|
+
click.echo()
|
|
158
|
+
click.echo("━" * 60)
|
|
159
|
+
|
|
160
|
+
total_files = len(semantic_results) if semantic_results else len(performance_results)
|
|
161
|
+
valid_semantic = sum(1 for r in semantic_results if r.is_valid) if semantic_results else 0
|
|
162
|
+
valid_perf = sum(1 for r in performance_results if r.is_valid) if performance_results else 0
|
|
163
|
+
|
|
164
|
+
if deps and perf:
|
|
165
|
+
valid = min(valid_semantic, valid_perf)
|
|
166
|
+
invalid = total_files - valid
|
|
167
|
+
elif deps:
|
|
168
|
+
valid = valid_semantic
|
|
169
|
+
invalid = total_files - valid
|
|
170
|
+
elif perf:
|
|
171
|
+
valid = valid_perf
|
|
172
|
+
invalid = total_files - valid
|
|
173
|
+
else:
|
|
174
|
+
valid = total_files
|
|
175
|
+
invalid = 0
|
|
176
|
+
|
|
177
|
+
click.echo(f"Total: {total_files} files")
|
|
178
|
+
click.echo(f"Valid: {valid} ({valid/total_files*100:.1f}%)" if total_files > 0 else "Valid: 0")
|
|
179
|
+
click.echo(f"Invalid: {invalid} ({invalid/total_files*100:.1f}%)" if total_files > 0 else "Invalid: 0")
|
|
180
|
+
click.echo("━" * 60)
|
|
181
|
+
|
|
182
|
+
# Exit code
|
|
183
|
+
if strict and invalid > 0:
|
|
184
|
+
click.echo()
|
|
185
|
+
click.echo("❌ Validation failed (strict mode)", err=True)
|
|
186
|
+
sys.exit(1)
|
|
187
|
+
elif invalid > 0:
|
|
188
|
+
click.echo()
|
|
189
|
+
click.echo("💡 Run 'voodocs fix' to automatically fix issues")
|
|
190
|
+
else:
|
|
191
|
+
click.echo()
|
|
192
|
+
click.echo("✅ All validations passed!")
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def display_text_results(
|
|
196
|
+
semantic_results: List[ValidationResult],
|
|
197
|
+
performance_results: List[PerformanceResult]
|
|
198
|
+
):
|
|
199
|
+
"""Display results in text format."""
|
|
200
|
+
|
|
201
|
+
# Display semantic results
|
|
202
|
+
if semantic_results:
|
|
203
|
+
click.echo("Semantic Validation Results:")
|
|
204
|
+
click.echo()
|
|
205
|
+
|
|
206
|
+
for result in semantic_results:
|
|
207
|
+
if result.is_valid:
|
|
208
|
+
click.echo(f"✅ {result.file_path}")
|
|
209
|
+
else:
|
|
210
|
+
click.echo(f"❌ {result.file_path}")
|
|
211
|
+
|
|
212
|
+
if result.missing_deps:
|
|
213
|
+
click.echo(f" Missing from ∂{{}}: {', '.join(sorted(result.missing_deps))}")
|
|
214
|
+
|
|
215
|
+
if result.extra_deps:
|
|
216
|
+
click.echo(f" Extra in ∂{{}}: {', '.join(sorted(result.extra_deps))}")
|
|
217
|
+
|
|
218
|
+
if result.errors:
|
|
219
|
+
for error in result.errors:
|
|
220
|
+
click.echo(f" Error: {error}")
|
|
221
|
+
|
|
222
|
+
if result.warnings:
|
|
223
|
+
for warning in result.warnings:
|
|
224
|
+
click.echo(f" Warning: {warning}")
|
|
225
|
+
|
|
226
|
+
click.echo()
|
|
227
|
+
|
|
228
|
+
# Display performance results
|
|
229
|
+
if performance_results:
|
|
230
|
+
click.echo("Performance Validation Results:")
|
|
231
|
+
click.echo()
|
|
232
|
+
|
|
233
|
+
for result in performance_results:
|
|
234
|
+
if result.is_valid:
|
|
235
|
+
click.echo(f"✅ {result.file_path}")
|
|
236
|
+
if hasattr(result, 'claimed_complexity') and result.claimed_complexity:
|
|
237
|
+
click.echo(f" Complexity: {result.claimed_complexity}")
|
|
238
|
+
else:
|
|
239
|
+
click.echo(f"❌ {result.file_path}")
|
|
240
|
+
if hasattr(result, 'claimed_complexity') and result.claimed_complexity:
|
|
241
|
+
click.echo(f" Claimed: {result.claimed_complexity}")
|
|
242
|
+
if hasattr(result, 'static_analysis') and result.static_analysis:
|
|
243
|
+
click.echo(f" Static Analysis: {result.static_analysis}")
|
|
244
|
+
|
|
245
|
+
if hasattr(result, 'warnings') and result.warnings:
|
|
246
|
+
for warning in result.warnings:
|
|
247
|
+
click.echo(f" Warning: {warning}")
|
|
248
|
+
|
|
249
|
+
if hasattr(result, 'suggestions') and result.suggestions:
|
|
250
|
+
for suggestion in result.suggestions:
|
|
251
|
+
click.echo(f" Suggestion: {suggestion}")
|
|
252
|
+
|
|
253
|
+
click.echo()
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def display_json_results(
|
|
257
|
+
semantic_results: List[ValidationResult],
|
|
258
|
+
performance_results: List[PerformanceResult],
|
|
259
|
+
output: Optional[str]
|
|
260
|
+
):
|
|
261
|
+
"""Display results in JSON format."""
|
|
262
|
+
import json
|
|
263
|
+
|
|
264
|
+
# Convert results to dicts
|
|
265
|
+
semantic_dicts = []
|
|
266
|
+
for r in semantic_results:
|
|
267
|
+
semantic_dicts.append({
|
|
268
|
+
"file_path": r.file_path,
|
|
269
|
+
"is_valid": r.is_valid,
|
|
270
|
+
"missing_deps": list(r.missing_deps) if hasattr(r, 'missing_deps') else [],
|
|
271
|
+
"extra_deps": list(r.extra_deps) if hasattr(r, 'extra_deps') else [],
|
|
272
|
+
"errors": r.errors if hasattr(r, 'errors') else [],
|
|
273
|
+
"warnings": r.warnings if hasattr(r, 'warnings') else [],
|
|
274
|
+
"suggestions": r.suggestions if hasattr(r, 'suggestions') else [],
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
# Performance results
|
|
278
|
+
perf_dicts = []
|
|
279
|
+
for r in performance_results:
|
|
280
|
+
perf_dicts.append({
|
|
281
|
+
"file_path": r.file_path,
|
|
282
|
+
"is_valid": r.is_valid,
|
|
283
|
+
"claimed_complexity": str(r.claimed_complexity) if hasattr(r, 'claimed_complexity') else None,
|
|
284
|
+
"warnings": r.warnings if hasattr(r, 'warnings') else [],
|
|
285
|
+
"suggestions": r.suggestions if hasattr(r, 'suggestions') else [],
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
data = {
|
|
289
|
+
"semantic": semantic_dicts,
|
|
290
|
+
"performance": perf_dicts,
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
json_str = json.dumps(data, indent=2)
|
|
294
|
+
|
|
295
|
+
if output:
|
|
296
|
+
Path(output).write_text(json_str)
|
|
297
|
+
click.echo(f"Results written to: {output}")
|
|
298
|
+
else:
|
|
299
|
+
click.echo(json_str)
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def display_html_results(
|
|
303
|
+
semantic_results: List[ValidationResult],
|
|
304
|
+
performance_results: List[PerformanceResult],
|
|
305
|
+
output: Optional[str]
|
|
306
|
+
):
|
|
307
|
+
"""Display results in HTML format."""
|
|
308
|
+
html = """
|
|
309
|
+
<!DOCTYPE html>
|
|
310
|
+
<html>
|
|
311
|
+
<head>
|
|
312
|
+
<title>VooDocs Validation Report</title>
|
|
313
|
+
<style>
|
|
314
|
+
body { font-family: Arial, sans-serif; margin: 20px; }
|
|
315
|
+
h1 { color: #333; }
|
|
316
|
+
.valid { color: green; }
|
|
317
|
+
.invalid { color: red; }
|
|
318
|
+
.file { margin: 10px 0; padding: 10px; border: 1px solid #ddd; }
|
|
319
|
+
</style>
|
|
320
|
+
</head>
|
|
321
|
+
<body>
|
|
322
|
+
<h1>VooDocs Validation Report</h1>
|
|
323
|
+
|
|
324
|
+
<h2>Semantic Validation</h2>
|
|
325
|
+
"""
|
|
326
|
+
|
|
327
|
+
for result in semantic_results:
|
|
328
|
+
status = "valid" if result.is_valid else "invalid"
|
|
329
|
+
html += f'<div class="file {status}">\n'
|
|
330
|
+
html += f'<strong>{result.file_path}</strong>: {"✅ Valid" if result.is_valid else "❌ Invalid"}<br>\n'
|
|
331
|
+
|
|
332
|
+
if not result.is_valid:
|
|
333
|
+
if result.missing_deps:
|
|
334
|
+
html += f'Missing: {", ".join(sorted(result.missing_deps))}<br>\n'
|
|
335
|
+
if result.extra_deps:
|
|
336
|
+
html += f'Extra: {", ".join(sorted(result.extra_deps))}<br>\n'
|
|
337
|
+
|
|
338
|
+
html += '</div>\n'
|
|
339
|
+
|
|
340
|
+
html += """
|
|
341
|
+
<h2>Performance Validation</h2>
|
|
342
|
+
"""
|
|
343
|
+
|
|
344
|
+
for result in performance_results:
|
|
345
|
+
status = "valid" if result.is_valid else "invalid"
|
|
346
|
+
html += f'<div class="file {status}">\n'
|
|
347
|
+
html += f'<strong>{result.file_path}</strong>: {"✅ Valid" if result.is_valid else "❌ Invalid"}<br>\n'
|
|
348
|
+
html += f'Claimed: {result.claimed_complexity}<br>\n'
|
|
349
|
+
|
|
350
|
+
if not result.is_valid:
|
|
351
|
+
html += f'Actual: {result.actual_complexity}<br>\n'
|
|
352
|
+
|
|
353
|
+
html += '</div>\n'
|
|
354
|
+
|
|
355
|
+
html += """
|
|
356
|
+
</body>
|
|
357
|
+
</html>
|
|
358
|
+
"""
|
|
359
|
+
|
|
360
|
+
if output:
|
|
361
|
+
Path(output).write_text(html)
|
|
362
|
+
click.echo(f"Results written to: {output}")
|
|
363
|
+
else:
|
|
364
|
+
click.echo(html)
|
package/lib/darkarts/__init__.py
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
1
|
+
"""@darkarts
|
|
2
|
+
⊢init:lib.darkarts.package
|
|
3
|
+
∂{}
|
|
4
|
+
⚠{python≥3.7}
|
|
5
|
+
⊨{∀import→exports-available,namespace:clean,¬side-effects-on-import}
|
|
6
|
+
🔒{pure-init,¬io,¬network,¬exec}
|
|
7
|
+
⚡{O(1):import-time}
|
|
8
|
+
|
|
9
|
+
Package initialization for lib.darkarts.
|
|
3
10
|
|
|
4
|
-
|
|
5
|
-
and computational reality, allowing AI to express solutions in mathematics
|
|
6
|
-
while getting executable results without writing code.
|
|
11
|
+
Module exports and namespace configuration.
|
|
7
12
|
"""
|
|
8
13
|
|
|
14
|
+
|
|
9
15
|
__version__ = "0.1.0-alpha"
|
|
10
16
|
__author__ = "Vooodooo"
|
|
11
17
|
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
1
|
+
"""@darkarts
|
|
2
|
+
⊢init:annotations.package
|
|
3
|
+
∂{}
|
|
4
|
+
⚠{python≥3.7}
|
|
5
|
+
⊨{∀import→exports-available,namespace:clean,¬side-effects-on-import}
|
|
6
|
+
🔒{pure-init,¬io,¬network,¬exec}
|
|
7
|
+
⚡{O(1):import-time}
|
|
8
|
+
|
|
9
|
+
Package initialization for annotations.
|
|
3
10
|
|
|
4
|
-
|
|
11
|
+
Module exports and namespace configuration.
|
|
5
12
|
"""
|
|
6
13
|
|
|
14
|
+
|
|
7
15
|
from .types import (
|
|
8
16
|
ParsedAnnotations,
|
|
9
17
|
ModuleAnnotation,
|
|
@@ -1,8 +1,21 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""@darkarts
|
|
2
|
+
⊢annotation-types:annotations.data-structures
|
|
3
|
+
∂{dataclasses,typing,enum}
|
|
4
|
+
⚠{python≥3.7}
|
|
5
|
+
⊨{∀dataclass:valid-schema,∀enum:valid-values,∀annotation:complete-representation,serializable:to-dict,multi-language:supported}
|
|
6
|
+
🔒{pure-data,¬io,¬side-effects,¬exec}
|
|
7
|
+
⚡{O(1):all-ops,lightweight-dataclasses}
|
|
8
|
+
|
|
2
9
|
DarkArts Annotation Types
|
|
3
10
|
|
|
4
|
-
Data structures for
|
|
5
|
-
|
|
11
|
+
Data structures for parsed @darkarts/@voodocs annotations with:
|
|
12
|
+
- Annotation types (function, method, class, module)
|
|
13
|
+
- Language support (Python, TypeScript, JavaScript, Java, C++, C#, Go, Rust)
|
|
14
|
+
- Complexity annotations (time, space, best/worst/average case)
|
|
15
|
+
- State transitions (from_state → to_state with conditions)
|
|
16
|
+
- Error cases (condition, error_type, description)
|
|
17
|
+
- Structured representations (FunctionAnnotation, ClassAnnotation, ModuleAnnotation)
|
|
18
|
+
""""
|
|
6
19
|
|
|
7
20
|
from dataclasses import dataclass, field
|
|
8
21
|
from typing import List, Dict, Optional, Any
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
1
|
+
"""@darkarts
|
|
2
|
+
⊢init:context.package
|
|
3
|
+
∂{}
|
|
4
|
+
⚠{python≥3.7}
|
|
5
|
+
⊨{∀import→exports-available,namespace:clean,¬side-effects-on-import}
|
|
6
|
+
🔒{pure-init,¬io,¬network,¬exec}
|
|
7
|
+
⚡{O(1):import-time}
|
|
8
|
+
|
|
9
|
+
Package initialization for context.
|
|
3
10
|
|
|
4
|
-
|
|
11
|
+
Module exports and namespace configuration.
|
|
5
12
|
"""
|
|
6
13
|
|
|
14
|
+
|
|
7
15
|
from .models import (
|
|
8
16
|
ContextFile,
|
|
9
17
|
Versioning,
|