154 lines
No EOL
5.4 KiB
Python
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()
|
|
} |