configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/relations.py
changeset 3 e7e0ae78773e
parent 0 2e8eeb919028
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/relations.py	Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/relations.py	Tue Aug 10 14:29:28 2010 +0300
@@ -40,13 +40,13 @@
             raise exceptions.NotSupportedException("No Relation class found for name %s" % relation_name)
 
     @ classmethod
-    def get_relations(cls, configuration, relation):
+    def get_relations(cls, relation):
         try:
             relations = []
             (left_expression,relation_name,right_expression) = parse_rule(relation)
-            relation = cls.get_relation_by_name(relation_name)(configuration, left_expression, right_expression)
+            relation = cls.get_relation_by_name(relation_name)(left_expression, right_expression)
             relations.append(relation)
-            propagated_relations = cls.get_relations(configuration, right_expression)
+            propagated_relations = cls.get_relations(right_expression)
             if propagated_relations:
                 for relation in propagated_relations:
                     relations.append(relation)
@@ -55,86 +55,32 @@
             return None
     
 
-class ConfigurationContext(rules.DefaultContext):
-    
-    def __init__(self, data):
-        rules.DefaultContext.__init__(self, data)
-        
-        # A note on the callback variables that follow:
-        # in order to collect rule execution results for the
-        # generation report, a callback system is implemented in
-        # ConfigurationContext.  It all boils down to ConfigureRelation
-        # using configure_expression_result_callback to catch the result
-        # in its execute() method. The ConfigurationContext just works as
-        # a "callback hub" because a reference to the context is available
-        # in all expression evaluations.
-        
-        # Callback called with a plugin.RelationExecutionResult object
-        # when a ConfigureExpression has been evaluated
-        self.configure_expression_result_callback = None
-        
-        # Callback called with the setting reference when a setting is dereferenced
-        # as a terminal expression
-        self.ref_terminal_callback = None
-        
-        # Callback called with the setting reference when a setting is dereferenced
-        # inside an EvalExpression
-        self.ref_eval_callback = None
-        
-        # Callback called with the setting reference when the value of a setting
-        # is set inside a SetExpression
-        self.ref_set_callback = None
-        
-    def handle_terminal(self, expression):
-        try:
-            value = self.data.get_default_view().get_feature(expression).get_value()
-            
-            # Got a valid ref, call the callback
-            if self.ref_terminal_callback:
-                self.ref_terminal_callback(expression)
-            
-            return value
-        except exceptions.NotFound,e:
-            """ return the expression itself if it is not a fearef """
-            #print "handle_terminal constant %s" % (expression)
-            try:
-                return eval(expression)
-            except (NameError,SyntaxError), e:
-                return expression
-
-    def eval(self, ast, expression, value):
-        #print "expression %s = %s" % (expression,value)
-        pass
-        
 class ConfigurationBaseRelation(rules.BaseRelation):
-    def __init__(self, data, left, right):
-        self.context = ConfigurationContext(data)
-        super(ConfigurationBaseRelation, self).__init__(data, left, right)
+    def __init__(self, left, right):
+        super(ConfigurationBaseRelation, self).__init__(None, left, right)
+        self.context = None
 
 class RequireRelation(ConfigurationBaseRelation):
     KEY = 'requires'
-    def __init__(self, data, left, right):
-        super(RequireRelation, self).__init__(data, left, right)
-        self.context = ConfigurationContext(data)
+    relation_name = 'requires'
+    def __init__(self, left, right):
+        super(RequireRelation, self).__init__(left, right)
 
 class ConfigureRelation(ConfigurationBaseRelation):
     KEY = 'configures'
-    def __init__(self, data, left, right):
-        self.context = ConfigurationContext(data)
-        super(ConfigureRelation, self).__init__(data, left, right)
+    relation_name = 'configures'
+    def __init__(self, left, right):
+        super(ConfigureRelation, self).__init__(left, right)
         
         # A plugin.RelationExecutionResult object is stored here
         self._execution_result = None
         
     
-    def execute(self):
+    def execute(self, context):
         self._execution_result = None
         exec_results = []
         
-        # Call BaseRelation.execute() and catch any ConfigureExpression result objects
-        self.context.configure_expression_result_callback = lambda result: exec_results.append(result)
-        result = rules.BaseRelation.execute(self)
-        self.context.configure_expression_result_callback = None
+        result = rules.BaseRelation.execute(self, context)
         
         if len(exec_results) > 0:
             # There should be only one ConfigureExpression inside a ConfigureRelation
@@ -157,9 +103,6 @@
         return True
     return False
 
-def handle_set(self, left, right):
-    left.set_value(right)
-
 def handle_filenamejoin(self, left, right):
     def extract_dirname(path):
         """Extract directory name (will always contain a trailing slash or backslash)"""
@@ -174,44 +117,21 @@
     
     return extract_dirname(left) + extract_filename(right)
 
-def handle_plus(self, left, right):
-    return left + right
-
-def handle_minus(self, left, right):
-    return left - right
-
-def handle_multiply(self, left, right):
-    return left * right
-
-def handle_divide(self, left, right):
-    return left / right
 
 class ConfigureExpression(rules.TwoOperatorExpression):
     PRECEDENCE = rules.PRECEDENCES['RELATION_OPERATORS']
     KEY = 'configures'
     OP = handle_configure
 
-    def eval(self, context):
+    def eval(self, context, **kwargs):
         input_refs = []
         affected_refs = []
         
-        # Evaluate the left-hand side expression, catching refs for the result
-        try:
-            context.ref_terminal_callback = lambda ref: input_refs.append(ref)
-            context.ref_eval_callback = lambda ref: input_refs.append(ref)
-            evaluated_left = self.left.eval(context)
-        finally:
-            context.ref_terminal_callback = None
-            context.ref_eval_callback = None
-        
+        # Evaluate the left-hand side expression
+        evaluated_left = self.left.eval(context, **kwargs)
         if evaluated_left:
-            # If left evaluated to True, evaluate the right-hand side and
-            # catch refs from SetExpression evaluations
-            try:
-                context.ref_set_callback = lambda ref: affected_refs.append(ref)
-                self.value = self.right.eval(context)
-            finally:
-                context.ref_set_callback = None
+            # If left evaluated to True, evaluate the right-hand side
+            self.value = self.right.eval(context, **kwargs)
         else:
             self.value = True
         
@@ -220,53 +140,20 @@
             for ref in self.ast.extract_refs(str(self.left)):
                 for key in context.get_keys(ref):
                     left_keys.append(key)
-
             for key in left_keys:
                 self.ast.add_error(key, { 'error_string' : 'CONFIGURES right side value is "False"',
                                           'left_key' : key,
                                           'rule' : self.ast.expression
                                           })
-        
-        # Return a RelationExecutionResult if necessary
-        if input_refs or affected_refs:
-            if context.configure_expression_result_callback:
-                result = plugin.RelationExecutionResult(utils.distinct_array(input_refs),
-                                                        utils.distinct_array(affected_refs))
-                context.configure_expression_result_callback(result)
-                
         return self.value
 
-class MultiplyExpression(rules.TwoOperatorExpression):
-    expression = "multiply_operation"
-    PRECEDENCE = rules.PRECEDENCES['MULDIV_OPERATORS']
-    KEY= '*'
-    OP = handle_multiply
-
-class DivideExpression(rules.TwoOperatorExpression):
-    expression = "divide_operation"
-    PRECEDENCE = rules.PRECEDENCES['MULDIV_OPERATORS']
-    KEY= '/'
-    OP = handle_divide
-
-class PlusExpression(rules.TwoOperatorExpression):
-    expression = "plus_operation"
-    PRECEDENCE = rules.PRECEDENCES['ADDSUB_OPERATORS']
-    KEY= '+'
-    OP = handle_plus
-
-class MinusExpression(rules.TwoOperatorExpression):
-    expression = "minus_operation"
-    PRECEDENCE = rules.PRECEDENCES['ADDSUB_OPERATORS']
-    KEY= '-'
-    OP = handle_minus
-
 class EvalExpression(rules.OneParamExpression):
     expression = "__eval__"
     PRECEDENCE = rules.PRECEDENCES['PREFIX_OPERATORS']
     KEY = '__eval__'
     
-    def __init__(self, ast, expression):
-        super(rules.OneParamExpression, self).__init__(ast)
+    def __init__(self, ast, expression): 
+        super(EvalExpression, self).__init__(ast, expression)
         self.expression = expression
         self._str_to_eval = eval(expression.expression)
         #self.default_view = default_view
@@ -277,26 +164,26 @@
         result.extend(utils.extract_delimited_tokens(self._str_to_eval, delimiters=('@{', '}')))
         return result
     
-    def eval(self, context):
+    def get_refs(self):
+        return self.extract_refs()
+    
+    def eval(self, context, **kwargs):
         # Using the configuration to pass the eval globals dictionary to here,
         # since there isn't any easy way to do this more elegantly
         globals_and_locals = {}
-        if hasattr(context.data, '_eval_expression_globals_dict'):
-            globals_and_locals = context.data._eval_expression_globals_dict
+        if hasattr(context, '_eval_expression_globals_dict'):
+            globals_and_locals = context._eval_expression_globals_dict
         
         str_to_eval = self._str_to_eval
         
         def expand_feature_ref(ref, index):
             var_name = "__fea_%05d" % index
-            globals_and_locals[var_name] = context.data.get_default_view().get_feature(ref)
-            if context.ref_eval_callback:
-                context.ref_eval_callback(ref)
+            globals_and_locals[var_name] = context.configuration.get_default_view().get_feature(ref)
             return var_name
+
         def expand_value_ref(ref, index):
             var_name = "__feaval_%05d" % index
-            globals_and_locals[var_name] = context.data.get_default_view().get_feature(ref).get_value()
-            if context.ref_eval_callback:
-                context.ref_eval_callback(ref)
+            globals_and_locals[var_name] = context.configuration.get_default_view().get_feature(ref).get_value()
             return var_name
         
         str_to_eval = utils.expand_delimited_tokens(str_to_eval, expand_feature_ref, delimiters=('@{', '}'))
@@ -317,7 +204,6 @@
             logging.getLogger('cone.ruleml').warning("Execution failed for eval: %s %s: %s" % (str_to_eval, type(e), e) )
             self.ast.add_error(self.expression, { 'error_string' : 'Execution failed for eval', 'str_to_eval' : str_to_eval, 'rule' : self.ast.expression })
 
-rules.OPERATORS[EvalExpression.KEY] = EvalExpression
 
 class FilenamejoinExpression(rules.TwoOperatorExpression):
     expression = "filenamejoin"
@@ -325,62 +211,12 @@
     KEY = 'filenamejoin'
     OP = handle_filenamejoin
     
+# Register relations and operators to rules
+rules.RELATIONS[RequireRelation.KEY] = RequireRelation
+rules.RELATIONS[ConfigureRelation.KEY] = ConfigureRelation
 rules.OPERATORS[FilenamejoinExpression.KEY] = FilenamejoinExpression
-    
-class SetExpression(rules.TwoOperatorExpression):
-    PRECEDENCE = rules.PRECEDENCES['SET_OPERATORS']
-    KEY= '='
-    OP = handle_set
-
-    def eval(self, context):
-        try:
-            variable = context.data.get_default_view().get_feature(self.left.expression)
-            value = self.right.eval(context)
-            variable.set_value(value)
-            logging.getLogger('cone.ruleml').info("Set %r = %r from %r" % (self.left.expression, value, self.right.expression) )
-            if context.ref_set_callback:
-                context.ref_set_callback(self.left.expression)
-            return True
-        except exceptions.NotFound,e:
-            self.ast.add_error(self.left.expression, { 'error_string' : 'Setting value failed, because of %s' % e,
-                               'left_key' : self.left.expression,
-                               'rule' : self.ast.expression})
-            return False
-
-_relations_and_operators_backup = None
-
-def register():
-    """
-    Register the relations and operators to ConE rules.
-    """
-    global _relations_and_operators_backup
-    if _relations_and_operators_backup is None:
-        # Create the backup copies of the dictionaries
-        rels_backup = rules.RELATIONS.copy()
-        ops_backup = rules.OPERATORS.copy()
-        assert rels_backup is not rules.RELATIONS
-        assert ops_backup is not rules.OPERATORS
-        _relations_and_operators_backup = (rels_backup, ops_backup)
-        
-        # Register relations and operators to rules
-        rules.RELATIONS[RequireRelation.KEY] = RequireRelation
-        rules.RELATIONS[ConfigureRelation.KEY] = ConfigureRelation
-        rules.OPERATORS[ConfigureExpression.KEY] = ConfigureExpression
-        rules.OPERATORS[PlusExpression.KEY] = PlusExpression
-        rules.OPERATORS[SetExpression.KEY] = SetExpression
-        rules.OPERATORS[MinusExpression.KEY] = MinusExpression
-        rules.OPERATORS[MultiplyExpression.KEY] = MultiplyExpression
-        rules.OPERATORS[DivideExpression.KEY] = DivideExpression
-
-def unregister():
-    """
-    Undo the changes made by a call to register().
-    """
-    global _relations_and_operators_backup
-    if _relations_and_operators_backup is not None:
-        rules.RELATIONS = _relations_and_operators_backup[0]
-        rules.OPERATORS = _relations_and_operators_backup[1]
-        _relations_and_operators_backup = None
+rules.OPERATORS[EvalExpression.KEY] = EvalExpression
+rules.OPERATORS[ConfigureExpression.KEY] = ConfigureExpression
 
 def parse_rule(rulestring):
     """