Skip to content

Commit 7df33ef

Browse files
committed
actually commit feature matrix script
1 parent 22aafae commit 7df33ef

1 file changed

Lines changed: 198 additions & 0 deletions

File tree

‎scripts/generate-feature-matrix.py‎

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Generate the XTDB feature compatibility matrix from test output.
4+
5+
This script runs all language tests and collects feature support information,
6+
then generates a markdown table that can be copied into the README.
7+
8+
Usage:
9+
python scripts/generate-feature-matrix.py
10+
"""
11+
12+
import subprocess
13+
import sys
14+
import re
15+
from collections import defaultdict
16+
17+
# Feature list (in order of appearance in matrix)
18+
FEATURES = [
19+
"Transit-Msgpack (COPY)",
20+
"NEST_ONE"
21+
]
22+
23+
# Language order
24+
LANGUAGES = [
25+
"Python",
26+
"Node.js",
27+
"Go",
28+
"Ruby",
29+
"Java",
30+
"Kotlin",
31+
"C",
32+
"C#",
33+
"Clojure",
34+
"Elixir",
35+
"Babashka",
36+
"PHP"
37+
]
38+
39+
# Map test output language names to display names
40+
LANGUAGE_MAP = {
41+
"python": "Python",
42+
"nodejs": "Node.js",
43+
"node": "Node.js",
44+
"go": "Go",
45+
"ruby": "Ruby",
46+
"java": "Java",
47+
"kotlin": "Kotlin",
48+
"c": "C",
49+
"csharp": "C#",
50+
"clojure": "Clojure",
51+
"elixir": "Elixir",
52+
"babashka": "Babashka",
53+
"php": "PHP"
54+
}
55+
56+
def run_tests():
57+
"""Run all language tests and capture output."""
58+
print("Running all language tests...")
59+
print("=" * 60)
60+
61+
try:
62+
result = subprocess.run(
63+
["mise", "run", "test:all"],
64+
capture_output=True,
65+
text=True,
66+
timeout=600,
67+
cwd="/workspaces/driver-examples"
68+
)
69+
70+
output = result.stdout + result.stderr
71+
print("Test run complete!")
72+
print("=" * 60)
73+
return output
74+
75+
except subprocess.TimeoutExpired:
76+
print("ERROR: Test run timed out after 10 minutes")
77+
sys.exit(1)
78+
except Exception as e:
79+
print(f"ERROR: Failed to run tests: {e}")
80+
sys.exit(1)
81+
82+
def parse_feature_reports(output):
83+
"""Parse XTDB_FEATURE_UNSUPPORTED lines from test output."""
84+
# Initialize: all languages support all features by default
85+
features = defaultdict(lambda: {
86+
"Transit-Msgpack (COPY)": True,
87+
"NEST_ONE": True
88+
})
89+
90+
# Initialize all languages
91+
for lang in LANGUAGES:
92+
features[lang] # Access to create entry with defaults
93+
94+
# Find unsupported feature declarations
95+
pattern = r'XTDB_FEATURE_UNSUPPORTED:\s+language=(\w+)\s+feature=([\w-]+)'
96+
97+
for match in re.finditer(pattern, output):
98+
lang = match.group(1)
99+
feature = match.group(2)
100+
101+
# Map to display name
102+
display_name = LANGUAGE_MAP.get(lang.lower(), lang)
103+
104+
# Map feature name to matrix column name
105+
if feature == "transit-msgpack":
106+
features[display_name]["Transit-Msgpack (COPY)"] = False
107+
elif feature == "nest-one":
108+
features[display_name]["NEST_ONE"] = False
109+
110+
return dict(features)
111+
112+
def generate_matrix(features):
113+
"""Generate markdown table from feature data."""
114+
115+
if not features:
116+
print("\n⚠️ No languages found!")
117+
print("This shouldn't happen - check the test output parsing logic.")
118+
return None
119+
120+
# Determine which features have at least one "no" (should be shown)
121+
features_to_show = []
122+
for feature in FEATURES:
123+
has_unsupported = any(
124+
not features.get(lang, {}).get(feature, True)
125+
for lang in LANGUAGES
126+
)
127+
if has_unsupported:
128+
features_to_show.append(feature)
129+
130+
if not features_to_show:
131+
return "## All features are supported in all languages! 🎉\n"
132+
133+
# Build markdown table
134+
lines = []
135+
lines.append("## Language Feature Compatibility Matrix")
136+
lines.append("")
137+
lines.append("The following matrix shows features that are not supported in some languages:")
138+
lines.append("")
139+
140+
# Header
141+
header = "| Language | " + " | ".join(features_to_show) + " |"
142+
separator = "|----------|" + "|".join(["-" * (len(f) + 2) for f in features_to_show]) + "|"
143+
144+
lines.append(header)
145+
lines.append(separator)
146+
147+
# Rows
148+
for lang in LANGUAGES:
149+
lang_features = features.get(lang, {})
150+
cells = [f"**{lang}**"]
151+
152+
for feature in features_to_show:
153+
supported = lang_features.get(feature, False)
154+
cells.append("✅" if supported else "❌")
155+
156+
lines.append("| " + " | ".join(cells) + " |")
157+
158+
lines.append("")
159+
lines.append("All languages support: Basic SQL, JSON, and Transit-JSON.")
160+
lines.append("")
161+
162+
return "\n".join(lines)
163+
164+
def main():
165+
print("XTDB Feature Matrix Generator")
166+
print("=" * 60)
167+
print()
168+
169+
# Run tests
170+
output = run_tests()
171+
172+
# Parse unsupported features
173+
features = parse_feature_reports(output)
174+
175+
# Count languages with unsupported features
176+
unsupported_count = sum(1 for lang, feats in features.items() if not all(feats.values()))
177+
178+
print(f"\nAnalyzed {len(features)} languages")
179+
print(f"Found {unsupported_count} languages with unsupported features")
180+
181+
# Generate matrix
182+
matrix = generate_matrix(features)
183+
184+
if matrix:
185+
print("\n" + "=" * 60)
186+
print("FEATURE COMPATIBILITY MATRIX")
187+
print("=" * 60)
188+
print()
189+
print(matrix)
190+
print()
191+
print("=" * 60)
192+
print("Copy the above matrix into README.md")
193+
print("=" * 60)
194+
else:
195+
sys.exit(1)
196+
197+
if __name__ == "__main__":
198+
main()

0 commit comments

Comments
 (0)