diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/relations.py --- 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): """