--- 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):
"""