127 lines
4.7 KiB
Python
127 lines
4.7 KiB
Python
#!/usr/bin/env python3
|
|
import json
|
|
import sys
|
|
import argparse
|
|
import os
|
|
from typing import Set, List, Dict, Any, Optional
|
|
|
|
# --- Constants (mirroring those used in tag structure) ---
|
|
TAGS = 'tags'
|
|
NAME = 'name'
|
|
TAG_TYPE = 'tagType'
|
|
FOLDER = 'Folder'
|
|
UDT_INSTANCE = 'UdtInstance'
|
|
|
|
|
|
def load_json_file(file_path: str) -> Optional[Dict[str, Any]]:
|
|
"""Loads JSON data from a file path. Returns the loaded dict or None on error."""
|
|
if not os.path.exists(file_path):
|
|
print(f"Error: File not found: '{file_path}'", file=sys.stderr)
|
|
return None
|
|
try:
|
|
with open(file_path, 'r') as f:
|
|
data = json.load(f)
|
|
# Basic validation that it's a dictionary (expected top level)
|
|
if not isinstance(data, dict):
|
|
print(f"Error: Expected JSON root to be an object/dictionary in '{file_path}'", file=sys.stderr)
|
|
return None
|
|
return data
|
|
except json.JSONDecodeError:
|
|
print(f"Error: Invalid JSON format in file: '{file_path}'", file=sys.stderr)
|
|
return None
|
|
except IOError as e:
|
|
print(f"Error reading file '{file_path}': {e}", file=sys.stderr)
|
|
return None
|
|
except Exception as e:
|
|
print(f"An unexpected error occurred while loading '{file_path}': {e}", file=sys.stderr)
|
|
return None
|
|
|
|
def _find_udt_instances_recursive(items: List[Dict[str, Any]], found_names: Set[str]):
|
|
"""Helper function to recursively find UDT instance names within a list of tags/folders."""
|
|
# Copy logic from check_tags.py
|
|
if not isinstance(items, list):
|
|
return # Stop recursion for this branch
|
|
|
|
for item in items:
|
|
if not isinstance(item, dict):
|
|
continue # Skip malformed items
|
|
|
|
item_tag_type = item.get(TAG_TYPE)
|
|
item_name = item.get(NAME)
|
|
|
|
if item_tag_type == UDT_INSTANCE and item_name:
|
|
found_names.add(item_name)
|
|
elif item_tag_type == FOLDER:
|
|
# Recursively check the tags within this folder
|
|
folder_tags = item.get(TAGS, [])
|
|
_find_udt_instances_recursive(folder_tags, found_names)
|
|
|
|
def extract_udt_names(file_path: str) -> Optional[Set[str]]:
|
|
"""
|
|
Loads a tags JSON file and extracts the names of all UDT instances.
|
|
Returns a set of names, or None if the file cannot be processed.
|
|
"""
|
|
print(f"Extracting UDT names from: {file_path}")
|
|
data = load_json_file(file_path)
|
|
if data is None:
|
|
return None
|
|
|
|
# Expecting a top-level object like {"tags": [...list of MCM folders...]}
|
|
if TAGS not in data or not isinstance(data.get(TAGS), list):
|
|
print(f"Error: '{file_path}' does not contain a top-level '{TAGS}' key with a list value.", file=sys.stderr)
|
|
return None
|
|
|
|
udt_names = set()
|
|
top_level_tags = data[TAGS]
|
|
# Start the recursive search from the list of MCM folders/tags
|
|
_find_udt_instances_recursive(top_level_tags, udt_names)
|
|
|
|
print(f" Found {len(udt_names)} UDT instance names.")
|
|
return udt_names
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="Compares the set of UDT Instance names found in two tags.json files.",
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter
|
|
)
|
|
parser.add_argument("file1", help="Path to the first JSON tags file (e.g., baseline).")
|
|
parser.add_argument("file2", help="Path to the second JSON tags file (e.g., new result).")
|
|
|
|
args = parser.parse_args()
|
|
|
|
print(f"Comparing UDT Instance names in:\n File 1: {args.file1}\n File 2: {args.file2}\n")
|
|
|
|
# Extract UDT names from both files
|
|
names1 = extract_udt_names(args.file1)
|
|
if names1 is None:
|
|
sys.exit(1)
|
|
|
|
names2 = extract_udt_names(args.file2)
|
|
if names2 is None:
|
|
sys.exit(1)
|
|
|
|
# Compare the sets of names
|
|
print("\n--- Comparison Results ---")
|
|
if names1 == names2:
|
|
print(f"Success: Both files contain the exact same {len(names1)} UDT instance names.")
|
|
sys.exit(0)
|
|
else:
|
|
print("Difference Found: The set of UDT instance names differs between the files.")
|
|
missing_in_file2 = sorted(list(names1 - names2))
|
|
added_in_file2 = sorted(list(names2 - names1))
|
|
|
|
if missing_in_file2:
|
|
print(f"\nNames in '{os.path.basename(args.file1)}' but NOT in '{os.path.basename(args.file2)}' ({len(missing_in_file2)}):")
|
|
for name in missing_in_file2:
|
|
print(f" - {name}")
|
|
|
|
if added_in_file2:
|
|
print(f"\nNames in '{os.path.basename(args.file2)}' but NOT in '{os.path.basename(args.file1)}' ({len(added_in_file2)}):")
|
|
for name in added_in_file2:
|
|
print(f" - {name}")
|
|
|
|
sys.exit(1) # Exit with a non-zero code to indicate difference
|
|
|
|
if __name__ == "__main__":
|
|
main() |