Skip to content

Commit 5804d63

Browse files
committed
big fix heterogenous naming
Signed-off-by: exploreriii <133720349+exploreriii@users.noreply.github.com>
1 parent 76c6995 commit 5804d63

File tree

2 files changed

+316
-1
lines changed

2 files changed

+316
-1
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Step 3 Refactor: Token class parser, exporter, and controller
4+
Enhanced to capture attributes, setters, add/remove methods, and key SDK methods (to_proto/from_proto).
5+
"""
6+
7+
import ast
8+
from pathlib import Path
9+
from typing import Dict, List, Any
10+
11+
12+
class TokenClassParser:
13+
"""Parses .py files to extract token class attributes and methods."""
14+
15+
def __init__(self, tokens_dir: Path):
16+
self.tokens_dir = tokens_dir
17+
self.errors: List[str] = []
18+
19+
def extract_classes_from_file(self, file_path: Path) -> Dict[str, Dict[str, List[str]]]:
20+
"""Extract classes with attributes and SDK methods from a Python file."""
21+
classes_info = {}
22+
try:
23+
with open(file_path, "r", encoding="utf-8") as f:
24+
tree = ast.parse(f.read(), filename=str(file_path))
25+
except Exception as e:
26+
self.errors.append(f"{file_path}: Failed to parse ({e})")
27+
return classes_info
28+
29+
for node in tree.body:
30+
if isinstance(node, ast.ClassDef):
31+
cls_name = node.name
32+
attributes = []
33+
setters = []
34+
others = []
35+
36+
for item in node.body:
37+
if isinstance(item, ast.FunctionDef):
38+
# Attributes from __init__
39+
if item.name == "__init__":
40+
attributes = [arg.arg for arg in item.args.args if arg.arg != "self"]
41+
42+
# SDK setters / repeated field methods
43+
elif item.name.startswith(("set_", "add_", "remove_")):
44+
setters.append(item.name)
45+
46+
# Other methods (proto conversion, validation, helpers)
47+
elif item.name in ("to_proto", "from_proto", "validate", "freeze", "unfreeze"):
48+
others.append(item.name)
49+
50+
# Optionally, include any other public methods
51+
elif not item.name.startswith("_"):
52+
others.append(item.name)
53+
54+
classes_info[cls_name] = {
55+
"attributes": attributes,
56+
"setters": setters,
57+
"other_methods": others
58+
}
59+
60+
return classes_info
61+
62+
def parse_all(self) -> Dict[str, Any]:
63+
"""Walk tokens directory and parse all classes."""
64+
all_classes_info = {}
65+
modules_seen = set()
66+
67+
for py_file in self.tokens_dir.glob("*.py"):
68+
if py_file.name == "__init__.py":
69+
continue
70+
module_name = py_file.stem
71+
modules_seen.add(module_name)
72+
class_info = self.extract_classes_from_file(py_file)
73+
if class_info:
74+
all_classes_info.update({f"{module_name}.{k}": v for k, v in class_info.items()})
75+
else:
76+
self.errors.append(f"{py_file}: No classes found or all failed parsing.")
77+
78+
return {"modules": sorted(modules_seen), "classes": all_classes_info, "errors": self.errors}
79+
80+
81+
class TokenClassExporter:
82+
"""Handles writing the parsed data to files."""
83+
84+
def __init__(self, output_dir: Path):
85+
self.output_dir = output_dir
86+
self.output_file = output_dir / "steps_3_token_classes_info_readable.py"
87+
self.error_file = output_dir / "steps_3_token_classes_errors.log"
88+
self.output_dir.mkdir(parents=True, exist_ok=True)
89+
90+
def write_class_info(self, modules: List[str], classes_info: Dict[str, Any]) -> None:
91+
with open(self.output_file, "w", encoding="utf-8") as f:
92+
f.write("# Auto-generated class info: attributes, setters, other methods\n\n")
93+
for mod in modules:
94+
f.write(f"from hiero_sdk_python.tokens import {mod}\n")
95+
f.write("\n")
96+
97+
for full_cls_name, info in sorted(classes_info.items()):
98+
file_name = full_cls_name.split(".")[0] + ".py"
99+
f.write(f"# File: {file_name}\n")
100+
f.write(f"{full_cls_name} = {{\n")
101+
f.write(" 'attributes': [\n")
102+
for attr in info['attributes']:
103+
f.write(f" '{attr}',\n")
104+
f.write(" ],\n")
105+
f.write(" 'setters': [\n")
106+
for setter in info['setters']:
107+
f.write(f" '{setter}',\n")
108+
f.write(" ],\n")
109+
f.write(" 'other_methods': [\n")
110+
for method in info['other_methods']:
111+
f.write(f" '{method}',\n")
112+
f.write(" ]\n")
113+
f.write("}\n\n")
114+
115+
def write_error_log(self, errors: List[str]) -> None:
116+
with open(self.error_file, "w", encoding="utf-8") as f:
117+
if errors:
118+
f.write("# Errors encountered during parsing\n\n")
119+
for err in errors:
120+
f.write(err + "\n")
121+
else:
122+
f.write("# No errors encountered\n")
123+
124+
def export(self, modules, classes_info, errors):
125+
self.write_class_info(modules, classes_info)
126+
self.write_error_log(errors)
127+
print(f"✅ Class info written to: {self.output_file}")
128+
print(f"🪶 Errors (if any) written to: {self.error_file}")
129+
130+
131+
class TokenClassExtractor:
132+
"""Controller that ties everything together."""
133+
134+
def __init__(self, project_root: Path):
135+
self.tokens_dir = project_root / "src" / "hiero_sdk_python" / "tokens"
136+
self.output_dir = project_root / "scripts" / "src_vs_proto"
137+
138+
def run(self):
139+
parser = TokenClassParser(self.tokens_dir)
140+
exporter = TokenClassExporter(self.output_dir)
141+
142+
print(f"🔍 Scanning token modules in {self.tokens_dir}...")
143+
result = parser.parse_all()
144+
145+
exporter.export(result["modules"], result["classes"], result["errors"])
146+
print("✅ Done.")
147+
148+
149+
if __name__ == "__main__":
150+
project_root = Path(__file__).resolve().parent.parent.parent
151+
TokenClassExtractor(project_root).run()

0 commit comments

Comments
 (0)