gateway/modules/shared/attributeUtils.py
ValueOn AG cf94b1115b ref
2025-05-26 07:04:30 +02:00

154 lines
No EOL
5.4 KiB
Python

"""
Shared utilities for model attributes and labels.
"""
from pydantic import BaseModel, Field
from typing import Dict, Any, List, Type, ClassVar
import inspect
import importlib
import os
class BaseModelWithUI(BaseModel):
"""Base model class with UI support and common functionality"""
@classmethod
def get_ui_schema(cls) -> Dict[str, Any]:
"""Get UI schema for frontend"""
return {
"fields": cls.fieldLabels if hasattr(cls, 'fieldLabels') else {},
"validations": cls.get_validations() if hasattr(cls, 'get_validations') else {}
}
def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary with proper validation"""
return self.model_dump()
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> 'BaseModelWithUI':
"""Create instance from dictionary with validation"""
return cls(**data)
@classmethod
def getModelAttributeDefinitions(cls) -> Dict[str, Any]:
"""
Get attribute definitions for this model class.
Override this method in model classes to provide custom attribute definitions.
Returns:
Dict[str, Any]: Dictionary of attribute definitions
"""
return {
name: {
"type": field.annotation.__name__ if hasattr(field.annotation, "__name__") else str(field.annotation),
"required": field.is_required() if hasattr(field, "is_required") else True,
"description": field.description if hasattr(field, "description") else "",
"label": cls.fieldLabels.get(name, Label(default=name)).getLabel() if hasattr(cls, "fieldLabels") else name
}
for name, field in cls.model_fields.items()
}
def getModelAttributes(modelClass):
"""
Get all attributes of a model class.
Args:
modelClass: The model class to get attributes from
Returns:
List[str]: List of attribute names
"""
return [attr for attr in dir(modelClass)
if not callable(getattr(modelClass, attr))
and not attr.startswith('_')
and attr not in ('metadata', 'query', 'query_class', 'label', 'field_labels')]
class Label(BaseModel):
"""
Label for an attribute or a class with support for multiple languages.
Attributes:
default: Default label text
translations: Dictionary of translations for different languages
"""
default: str = Field(..., description="Default label text")
translations: Dict[str, str] = Field(default_factory=dict, description="Translations for different languages")
class Config:
title = "Label"
description = "A label with support for multiple languages"
schema_extra = {
"example": {
"default": "Document",
"translations": {
"en": "Document",
"fr": "Document"
}
}
}
def getLabel(self, language: str = None) -> str:
"""
Returns the label in the specified language, or the default value if not available.
Args:
language: Language code to get the label for
Returns:
str: Label text in the specified language or default
"""
if language and language in self.translations:
return self.translations[language]
return self.default
def getModelClasses() -> Dict[str, Type[BaseModel]]:
"""
Dynamically get all model classes from all model modules.
Returns:
Dict[str, Type[BaseModel]]: Dictionary of model class names to their classes
"""
modelClasses = {}
# Get the interfaces directory path
interfaces_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'interfaces')
# Find all model files
for filename in os.listdir(interfaces_dir):
if filename.endswith('Model.py'):
# Convert filename to module name (e.g., gatewayModel.py -> gatewayModel)
module_name = filename[:-3]
# Import the module dynamically
module = importlib.import_module(f'modules.interfaces.{module_name}')
# Get all classes from the module
for name, obj in inspect.getmembers(module):
if inspect.isclass(obj) and issubclass(obj, BaseModel) and obj != BaseModel:
modelClasses[name] = obj
return modelClasses
def getModelAttributeDefinitions(modelClass: Type[BaseModel] = None, userLanguage: str = "en") -> Dict[str, Any]:
"""
Get attribute definitions for model classes.
If modelClass is provided, returns attributes for that specific class.
If no modelClass is provided, returns attributes for all model classes.
Args:
modelClass: Optional specific model class to get attributes for
userLanguage: Language code for translations (default: "en")
Returns:
Dict[str, Any]: Dictionary of model class names to their attribute definitions
"""
if modelClass:
return getModelAttributes(modelClass)
# Get all model classes
modelClasses = getModelClasses()
# Create dictionary of model class names to their attribute definitions
return {
name: getModelAttributes(cls)
for name, cls in modelClasses.items()
}