From e465c40ccf10e38fb07924ca621367d944f26b07 Mon Sep 17 00:00:00 2001 From: laansdole Date: Wed, 21 Jan 2026 15:06:29 +0700 Subject: [PATCH] feat: update dev tools --- check/check.py | 34 ++++++++++++++-- tools/sync_vuegraphs.py | 48 +++++++++++++++++++++++ tools/validate_all_yamls.py | 77 +++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 tools/sync_vuegraphs.py create mode 100644 tools/validate_all_yamls.py diff --git a/check/check.py b/check/check.py index 39ba0407..d3027329 100755 --- a/check/check.py +++ b/check/check.py @@ -19,7 +19,6 @@ class DesignError(RuntimeError): """Raised when a workflow design cannot be loaded or validated.""" - def _allowed_node_types() -> set[str]: names = set(iter_node_schemas().keys()) if not names: @@ -73,7 +72,9 @@ def load_config( data = prepare_design_mapping(raw_data, source=str(config_path)) - schema_errors = validate_design(data, set_defaults=set_defaults, fn_module_ref=fn_module) + schema_errors = validate_design( + data, set_defaults=set_defaults, fn_module_ref=fn_module + ) if schema_errors: formatted = "\n".join(f"- {err}" for err in schema_errors) raise DesignError(f"Design validation failed for '{config_path}':\n{formatted}") @@ -86,7 +87,9 @@ def load_config( logic_errors = check_workflow_structure(data) if logic_errors: formatted = "\n".join(f"- {err}" for err in logic_errors) - raise DesignError(f"Workflow logical issues detected for '{config_path}':\n{formatted}") + raise DesignError( + f"Workflow logical issues detected for '{config_path}':\n{formatted}" + ) else: print("Workflow OK.") @@ -119,3 +122,28 @@ def check_config(yaml_content: Any) -> str: return str(e) return "" + + +def main(): + import argparse + import sys + + parser = argparse.ArgumentParser(description="Validate workflow design file.") + parser.add_argument( + "--path", type=Path, required=True, help="Path to the design file." + ) + args = parser.parse_args() + + try: + load_config(args.path) + print(f"Design '{args.path}' is valid.") + except DesignError as e: + print(f"Validation failed: {e}") + sys.exit(1) + except Exception as e: + print(f"An unexpected error occurred: {e}") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/tools/sync_vuegraphs.py b/tools/sync_vuegraphs.py new file mode 100644 index 00000000..7ce5f151 --- /dev/null +++ b/tools/sync_vuegraphs.py @@ -0,0 +1,48 @@ +import os +import glob +import requests +import yaml +from pathlib import Path + +# Configuration +API_URL = "http://localhost:6400/api/vuegraphs/upload/content" +YAML_DIR = "yaml_instance" + +def sync_yaml_to_vuegraphs(): + """Reads all YAML files and uploads them to the VueGraph database.""" + print(f"Syncing YAML files from {YAML_DIR} to {API_URL}...") + + yaml_files = glob.glob(os.path.join(YAML_DIR, "*.yaml")) + + for file_path in yaml_files: + try: + filename = Path(file_path).stem # simulation_hospital_lmstudio + + with open(file_path, "r") as f: + content = f.read() + + # Basic validation to ensure it's a valid YAML + try: + yaml.safe_load(content) + except yaml.YAMLError as e: + print(f"Skipping {filename}: Invalid YAML - {e}") + continue + + # Upload to VueGraph API + payload = { + "filename": filename, + "content": content + } + + response = requests.post(API_URL, json=payload) + + if response.status_code == 200: + print(f"Synced: {filename}") + else: + print(f"Failed: {filename} - {response.status_code} {response.text}") + + except Exception as e: + print(f"Error processing {file_path}: {e}") + +if __name__ == "__main__": + sync_yaml_to_vuegraphs() diff --git a/tools/validate_all_yamls.py b/tools/validate_all_yamls.py new file mode 100644 index 00000000..b4f27ff7 --- /dev/null +++ b/tools/validate_all_yamls.py @@ -0,0 +1,77 @@ +import sys +import subprocess +from pathlib import Path + + +def validate_all(): + base_dir = Path("yaml_instance") + if not base_dir.exists(): + print(f"Directory {base_dir} not found.") + sys.exit(1) + + # Recursive search for all .yaml files + files = sorted(list(base_dir.rglob("*.yaml"))) + + if not files: + print("No YAML files found.") + return + + print( + f"Found {len(files)} YAML files. Running FULL validation via check.check...\n" + ) + + passed = 0 + failed = 0 + failed_files = [] + + for yaml_file in files: + # Use relative path for cleaner output + try: + rel_path = yaml_file.relative_to(Path.cwd()) + except ValueError: + rel_path = yaml_file + + # NOW we run check.check, which we just patched to have a main() + # This performs the stricter load_config() validation + cmd = [sys.executable, "-m", "check.check", "--path", str(yaml_file)] + + try: + result = subprocess.run(cmd, capture_output=True, text=True) + + if result.returncode == 0: + print(f"{rel_path}") + passed += 1 + else: + print(f"{rel_path}") + # Indent error output + if result.stdout: + print(" stdout:", result.stdout.strip().replace("\n", "\n ")) + # Validation errors usually print to stdout/stderr depending on impl + # Our new main prints to stdout for success/failure message + failed += 1 + failed_files.append(str(rel_path)) + except Exception as e: + print(f"{rel_path} (Execution Failed)") + print(f" Error: {e}") + failed += 1 + failed_files.append(str(rel_path)) + + print("\n" + "=" * 40) + print(f"Validation Summary") + print("=" * 40) + print(f"Total Files: {len(files)}") + print(f"Passed: {passed}") + print(f"Failed: {failed}") + + if failed > 0: + print("\nFailed Files:") + for f in failed_files: + print(f"- {f}") + sys.exit(1) + else: + print("\nAll files passed validation.") + sys.exit(0) + + +if __name__ == "__main__": + validate_all()