variables.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. from typing import Any, Dict, List, Tuple
  2. from .config import ConfigManager
  3. class Variable:
  4. """Data class for variable information."""
  5. def __init__(self, name: str, description: str = "", value: Any = None, var_type: str = "string", options: List[Any] = None, enabled: bool = True):
  6. self.name = name
  7. self.description = description
  8. self.value = value
  9. self.type = var_type # e.g., string, integer, boolean, choice
  10. self.options = options if options is not None else [] # For choice type
  11. self.enabled = enabled # Whether this variable is enabled (default: True)
  12. class VariableGroup():
  13. """Data class for variable groups."""
  14. def __init__(self, name: str, description: str = "", vars: List[Variable] = None, enabled: bool = True):
  15. self.name = name
  16. self.description = description
  17. self.vars = vars if vars is not None else []
  18. self.enabled = enabled # Whether this variable group is enabled
  19. self.prompt_to_set = "" # Custom prompt message
  20. self.prompt_to_enable = "" # Custom prompt message when asking to enable this group
  21. def is_enabled(self) -> bool:
  22. """Check if this variable group is enabled."""
  23. return self.enabled
  24. def enable(self) -> None:
  25. """Enable this variable group."""
  26. self.enabled = True
  27. def disable(self) -> None:
  28. """Disable this variable group."""
  29. self.enabled = False
  30. def get_enabled_variables(self) -> List[Variable]:
  31. """Get all enabled variables in this group."""
  32. return [var for var in self.vars if var.enabled]
  33. def disable_variables_not_in_template(self, template_vars: List[str]) -> None:
  34. """Disable all variables that are not found in the template variables.
  35. Args:
  36. template_vars: List of variable names used in the template
  37. """
  38. for var in self.vars:
  39. if var.name not in template_vars:
  40. var.enabled = False
  41. @classmethod
  42. def from_dict(cls, name: str, config: Dict[str, Any]) -> "VariableGroup":
  43. """Create a VariableGroup from a dictionary configuration."""
  44. variables = []
  45. vars_config = config.get("vars", {})
  46. for var_name, var_config in vars_config.items():
  47. var_type = var_config.get("var_type", "string") # Default to string if not specified
  48. enabled = var_config.get("enabled", True) # Default to enabled if not specified
  49. variables.append(Variable(
  50. name=var_name,
  51. description=var_config.get("description", ""),
  52. value=var_config.get("value"),
  53. var_type=var_type,
  54. enabled=enabled
  55. ))
  56. return cls(
  57. name=name,
  58. description=config.get("description", ""),
  59. vars=variables,
  60. enabled=config.get("enabled", True) # Default to enabled if not specified
  61. )
  62. class VariableManager:
  63. """Manager class for handling collections of VariableGroups.
  64. The VariableManager centralizes variable-related operations for:
  65. - Managing VariableGroups
  66. - Validating template variables
  67. - Filtering variables for specific templates
  68. - Resolving variable defaults with priority handling
  69. """
  70. def __init__(self, variable_groups: List[VariableGroup] = None, config_manager: ConfigManager = None):
  71. """Initialize the VariableManager with a list of VariableGroups and ConfigManager."""
  72. self.variable_groups = variable_groups if variable_groups is not None else []
  73. self.config_manager = config_manager if config_manager is not None else ConfigManager()
  74. def add_group(self, group: VariableGroup) -> None:
  75. """Add a VariableGroup to the manager."""
  76. if not isinstance(group, VariableGroup):
  77. raise ValueError("group must be a VariableGroup instance")
  78. self.variable_groups.append(group)
  79. def disable_variables_not_in_template(self, template_vars: List[str]) -> None:
  80. """Disable all variables in all groups that are not found in the template variables.
  81. Args:
  82. template_vars: List of variable names used in the template
  83. """
  84. for group in self.variable_groups:
  85. group.disable_variables_not_in_template(template_vars)
  86. def get_all_variable_names(self) -> List[str]:
  87. """Get all variable names from all variable groups."""
  88. return [var.name for group in self.variable_groups for var in group.vars]
  89. def has_variable(self, name: str) -> bool:
  90. """Check if a variable exists in any group."""
  91. for group in self.variable_groups:
  92. for var in group.vars:
  93. if var.name == name:
  94. return True
  95. return False
  96. def validate_template_variables(self, template_vars: List[str]) -> Tuple[bool, List[str]]:
  97. """Validate if all template variables exist in the variable groups.
  98. Args:
  99. template_vars: List of variable names used in the template
  100. Returns:
  101. Tuple of (success: bool, missing_variables: List[str])
  102. """
  103. all_variables = self.get_all_variable_names()
  104. missing_variables = [var for var in template_vars if var not in all_variables]
  105. success = len(missing_variables) == 0
  106. return success, missing_variables
  107. def filter_variables_for_template(self, template_vars: List[str]) -> Dict[str, Any]:
  108. """Filter the variable groups to only include variables needed by the template.
  109. Args:
  110. template_vars: List of variable names used in the template
  111. Returns:
  112. Dictionary with filtered variable groups and their variables, including group metadata
  113. """
  114. filtered_vars = {}
  115. for group in self.variable_groups:
  116. group_has_template_vars = False
  117. group_vars = {}
  118. for variable in group.vars:
  119. if variable.name in template_vars:
  120. group_has_template_vars = True
  121. group_vars[variable.name] = {
  122. 'name': variable.name,
  123. 'description': variable.description,
  124. 'value': variable.value,
  125. 'type': variable.type,
  126. 'options': getattr(variable, 'options', []),
  127. 'enabled': variable.enabled
  128. }
  129. # Only include groups that have variables used by the template
  130. if group_has_template_vars:
  131. filtered_vars[group.name] = {
  132. 'description': group.description,
  133. 'enabled': group.enabled,
  134. 'prompt_to_set': getattr(group, 'prompt_to_set', ''),
  135. 'prompt_to_enable': getattr(group, 'prompt_to_enable', ''),
  136. 'vars': group_vars
  137. }
  138. return filtered_vars
  139. def get_module_defaults(self, template_vars: List[str]) -> Dict[str, Any]:
  140. """Get default values from module variable definitions for template variables.
  141. Args:
  142. template_vars: List of variable names used in the template
  143. Returns:
  144. Dictionary mapping variable names to their default values
  145. """
  146. defaults = {}
  147. for group in self.variable_groups:
  148. for variable in group.vars:
  149. if variable.name in template_vars and variable.value is not None:
  150. defaults[variable.name] = variable.value
  151. return defaults
  152. def resolve_variable_defaults(self, module_name: str, template_vars: List[str], template_defaults: Dict[str, Any] = None) -> Dict[str, Any]:
  153. """Resolve variable default values with hardcoded priority handling.
  154. Priority order (hardcoded):
  155. 1. Module variable defaults (low priority)
  156. 2. Template's built-in defaults from |default() filters (medium priority)
  157. 3. User config defaults (high priority)
  158. Args:
  159. module_name: Name of the module (for config lookup)
  160. template_vars: List of variable names used in the template
  161. template_defaults: Dictionary of template's built-in default values
  162. Returns:
  163. Dictionary of variable names to their resolved default values
  164. """
  165. if template_defaults is None:
  166. template_defaults = {}
  167. # Priority 1: Start with module variable defaults (low priority)
  168. defaults = self.get_module_defaults(template_vars)
  169. # Priority 2: Override with template's built-in defaults (medium priority)
  170. defaults.update(template_defaults)
  171. # Priority 3: Override with user config defaults (high priority)
  172. user_config_defaults = self.config_manager.get_variable_defaults(module_name)
  173. for var_name in template_vars:
  174. if var_name in user_config_defaults:
  175. defaults[var_name] = user_config_defaults[var_name]
  176. return defaults
  177. def get_summary(self) -> Dict[str, Any]:
  178. """Get a summary of all variable groups and their contents."""
  179. summary = {
  180. 'total_groups': len(self.variable_groups),
  181. 'total_variables': len(self.get_all_variable_names()),
  182. 'groups': []
  183. }
  184. for group in self.variable_groups:
  185. group_info = {
  186. 'name': group.name,
  187. 'description': group.description,
  188. 'variable_count': len(group.vars),
  189. 'variables': [var.name for var in group.vars]
  190. }
  191. summary['groups'].append(group_info)
  192. return summary