yaml_utils.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import ruamel.yaml
  2. import sys
  3. import re
  4. import warnings
  5. # Suppress the specific warning from ruamel.yaml about floats without dots
  6. warnings.simplefilter('ignore', ruamel.yaml.error.MantissaNoDotYAML1_1Warning)
  7. def convert_to_plain_python_types(data):
  8. """
  9. Recursively converts ruamel.yaml specific types into plain Python types.
  10. """
  11. if isinstance(data, ruamel.yaml.comments.CommentedMap):
  12. return {convert_to_plain_python_types(k): convert_to_plain_python_types(v) for k, v in data.items()}
  13. elif isinstance(data, ruamel.yaml.comments.CommentedSeq):
  14. return [convert_to_plain_python_types(i) for i in data]
  15. elif isinstance(data, ruamel.yaml.scalarstring.ScalarString):
  16. return str(data)
  17. elif isinstance(data, ruamel.yaml.anchor.Anchor):
  18. return data.value
  19. return data
  20. def load_unity_yaml(file_path):
  21. """
  22. Safely loads a Unity YAML file, which may contain multiple documents,
  23. into a list of Python objects.
  24. """
  25. try:
  26. with open(file_path, 'r', encoding='utf-8') as f:
  27. yaml_content = f.read()
  28. # Use regex to fix the Unity-specific shorthand tags.
  29. # This looks for "--- !u!### &..." and replaces it with a valid tag format.
  30. processed_content = re.sub(r'--- !u!(\d+) &', r'--- !<tag:unity3d.com,2011:\1> &', yaml_content)
  31. # Unity files start with a %YAML directive, which ruamel.yaml can handle.
  32. # The documents are separated by '---'.
  33. yaml = ruamel.yaml.YAML(typ='rt') # Use round-trip mode to handle custom tags
  34. # allow_duplicate_keys=True is important for some Unity files
  35. yaml.allow_duplicate_keys = True
  36. documents = list(yaml.load_all(processed_content))
  37. return documents
  38. except FileNotFoundError:
  39. print(f"Error: File not found at {file_path}", file=sys.stderr)
  40. return []
  41. except ruamel.yaml.YAMLError as e:
  42. print(f"Error parsing YAML file {file_path}: {e}", file=sys.stderr)
  43. return []
  44. except Exception as e:
  45. print(f"An unexpected error occurred while reading {file_path}: {e}", file=sys.stderr)
  46. return []
  47. if __name__ == '__main__':
  48. # Example usage:
  49. # This allows testing the module directly.
  50. # You would run this from the root of the project as:
  51. # python Assets/LLM/source/utils/yaml_utils.py <path_to_some_asset>.asset
  52. if len(sys.argv) > 1:
  53. file_to_load = sys.argv[1]
  54. print(f"Attempting to load Unity YAML file: {file_to_load}")
  55. docs = load_unity_yaml(file_to_load)
  56. if docs:
  57. print(f"Successfully loaded {len(docs)} documents.")
  58. for i, doc in enumerate(docs):
  59. print(f"--- Document {i+1} ---")
  60. # A simple print might not show all nested details, but it's a good check.
  61. print(doc)
  62. print()
  63. else:
  64. print("Failed to load documents or the file was empty.")
  65. else:
  66. print("Please provide a file path as a command-line argument to test the loader.")