You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
233 lines
7.3 KiB
233 lines
7.3 KiB
from pydantic import BaseModel, Field
|
|
import yaml
|
|
import json
|
|
from swarms.utils.loguru_logger import logger
|
|
from typing import Any, Dict
|
|
from typing import Type
|
|
from dataclasses import is_dataclass, fields
|
|
|
|
|
|
def get_type_name(typ: Type) -> str:
|
|
"""Map Python types to simple string representations."""
|
|
if hasattr(typ, "__name__"):
|
|
return typ.__name__
|
|
return str(typ)
|
|
|
|
|
|
def create_yaml_schema_from_dict(
|
|
data: Dict[str, Any], model_class: Type
|
|
) -> str:
|
|
"""
|
|
Generate a YAML schema based on a dictionary and a class (can be a Pydantic model, regular class, or dataclass).
|
|
|
|
Args:
|
|
data: The dictionary with key-value pairs where keys are attribute names and values are example data.
|
|
model_class: The class which the data should conform to, used for obtaining type information.
|
|
|
|
Returns:
|
|
A string containing the YAML schema.
|
|
|
|
Example usage:
|
|
>>> data = {'name': 'Alice', 'age: 30, 'is_active': True}
|
|
>>> print(create_yaml_schema_from_dict(data, User))
|
|
|
|
"""
|
|
schema = {}
|
|
if is_dataclass(model_class):
|
|
for field in fields(model_class):
|
|
schema[field.name] = {
|
|
"type": get_type_name(field.type),
|
|
"default": (
|
|
field.default
|
|
if field.default != field.default_factory
|
|
else None
|
|
),
|
|
"description": field.metadata.get(
|
|
"description", "No description provided"
|
|
),
|
|
}
|
|
elif isinstance(model_class, BaseModel):
|
|
for field_name, model_field in model_class.__fields__.items():
|
|
field_info = model_field.field_info
|
|
schema[field_name] = {
|
|
"type": get_type_name(model_field.outer_type_),
|
|
"default": field_info.default,
|
|
"description": (
|
|
field_info.description
|
|
or "No description provided."
|
|
),
|
|
}
|
|
else:
|
|
# Fallback for regular classes (non-dataclass, non-Pydantic)
|
|
for attr_name, attr_value in data.items():
|
|
attr_type = type(attr_value)
|
|
schema[attr_name] = {
|
|
"type": get_type_name(attr_type),
|
|
"description": "No description provided",
|
|
}
|
|
|
|
return yaml.safe_dump(schema, sort_keys=False)
|
|
|
|
|
|
def pydantic_type_to_yaml_schema(pydantic_type):
|
|
"""
|
|
Map Pydantic types to YAML schema types.
|
|
|
|
Args:
|
|
pydantic_type (type): The Pydantic type to be mapped.
|
|
|
|
Returns:
|
|
str: The corresponding YAML schema type.
|
|
|
|
"""
|
|
type_mapping = {
|
|
int: "integer",
|
|
float: "number",
|
|
str: "string",
|
|
bool: "boolean",
|
|
list: "array",
|
|
dict: "object",
|
|
}
|
|
# For more complex types or generics, you would expand this mapping
|
|
base_type = getattr(pydantic_type, "__origin__", pydantic_type)
|
|
if base_type is None:
|
|
base_type = pydantic_type
|
|
return type_mapping.get(base_type, "string")
|
|
|
|
|
|
class YamlModel(BaseModel):
|
|
"""
|
|
A Pydantic model class for working with YAML data.
|
|
|
|
|
|
Example usage:
|
|
# Example usage with an extended YamlModel
|
|
>>> class User(YamlModel):
|
|
name: str
|
|
age: int
|
|
is_active: bool
|
|
|
|
# Create an instance of the User model
|
|
>>> user = User(name="Alice", age=30, is_active=True)
|
|
|
|
# Serialize the User instance to YAML and print it
|
|
>>> print(user.to_yaml())
|
|
|
|
# Convert JSON to YAML and print
|
|
>>> json_string = '{"name": "Bob", "age": 25, "is_active": false}'
|
|
>>> print(YamlModel.json_to_yaml(json_string))
|
|
|
|
# Save the User instance to a YAML file
|
|
>>> user.save_to_yaml('user.yaml')
|
|
"""
|
|
|
|
input_dict: Dict[str, Any] = Field(
|
|
None,
|
|
title="Data",
|
|
description="The data to be serialized to YAML.",
|
|
)
|
|
|
|
def to_yaml(self):
|
|
"""
|
|
Serialize the Pydantic model instance to a YAML string.
|
|
"""
|
|
return yaml.safe_dump(self.input_dict, sort_keys=False)
|
|
|
|
def from_yaml(self, cls, yaml_str: str):
|
|
"""
|
|
Create an instance of the class from a YAML string.
|
|
|
|
Args:
|
|
yaml_str (str): The YAML string to parse.
|
|
|
|
Returns:
|
|
cls: An instance of the class with attributes populated from the YAML data.
|
|
Returns None if there was an error loading the YAML data.
|
|
"""
|
|
try:
|
|
data = yaml.safe_load(yaml_str)
|
|
return cls(**data)
|
|
except ValueError as error:
|
|
logger.error(f"Error loading YAML data: {error}")
|
|
return None
|
|
|
|
@staticmethod
|
|
def json_to_yaml(self, json_str: str):
|
|
"""
|
|
Convert a JSON string to a YAML string.
|
|
"""
|
|
data = json.loads(
|
|
json_str
|
|
) # Convert JSON string to dictionary
|
|
return yaml.dump(data)
|
|
|
|
def save_to_yaml(self, filename: str):
|
|
"""
|
|
Save the Pydantic model instance as a YAML file.
|
|
"""
|
|
yaml_data = self.to_yaml()
|
|
with open(filename, "w") as file:
|
|
file.write(yaml_data)
|
|
|
|
# TODO: Implement a method to create a YAML schema from the model fields
|
|
# @classmethod
|
|
# def create_yaml_schema(cls):
|
|
# """
|
|
# Generate a YAML schema based on the fields of the given BaseModel Class.
|
|
|
|
# Args:
|
|
# cls: The class for which the YAML schema is generated.
|
|
|
|
# Returns:
|
|
# A YAML representation of the schema.
|
|
|
|
# """
|
|
# schema = {}
|
|
# for field_name, model_field in cls.model_fields.items(): # Use model_fields
|
|
# field_type = model_field.type_ # Assuming type_ for field type access
|
|
# field_info = model_field # FieldInfo object already
|
|
# schema[field_name] = {
|
|
# 'type': pydantic_type_to_yaml_schema(field_type),
|
|
# 'description': field_info.description or "No description provided."
|
|
# }
|
|
# if field_info is not None: # Check for default value directly
|
|
# schema[field_name]['default'] = field_info.default
|
|
# return yaml.safe_dump(schema, sort_keys=False)
|
|
|
|
def create_yaml_schema_from_dict(
|
|
self, data: Dict[str, Any], model_class: Type
|
|
) -> str:
|
|
"""
|
|
Generate a YAML schema based on a dictionary and a class (can be a Pydantic model, regular class, or dataclass).
|
|
|
|
Args:
|
|
data: The dictionary with key-value pairs where keys are attribute names and values are example data.
|
|
model_class: The class which the data should conform to, used for obtaining type information.
|
|
|
|
Returns:
|
|
A string containing the YAML schema.
|
|
|
|
Example usage:
|
|
>>> data = {'name': 'Alice', 'age: 30, 'is_active': True}
|
|
"""
|
|
return create_yaml_schema_from_dict(data, model_class)
|
|
|
|
def yaml_to_dict(self, yaml_str: str):
|
|
"""
|
|
Convert a YAML string to a Python dictionary.
|
|
"""
|
|
return yaml.safe_load(yaml_str)
|
|
|
|
def dict_to_yaml(self, data: Dict[str, Any]):
|
|
"""
|
|
Convert a Python dictionary to a YAML string.
|
|
"""
|
|
return yaml.safe_dump(data, sort_keys=False)
|
|
|
|
|
|
# dict = {'name': 'Alice', 'age': 30, 'is_active': True}
|
|
|
|
# # Comvert the dictionary to a YAML schema dict to yaml
|
|
# yaml_model = YamlModel().dict_to_yaml(dict)
|
|
# print(yaml_model)
|