def __compile_function(self, function): parameters = [] for param in function.function_parameters: cparam = CompiledExpression(param, user_functions=self.user_functions, known_variables=self.__all_known_variables) parameters.append(cparam) self.__collect_attributes( cparam.getDependencies() ) function.function_parameters = tuple(parameters)
def __init__(self, name, attribute_value_select, user_functions={}, known_variables={}): self.name = name self.attributes = attributes = {} self.reverse_deps = reverse_deps = {} for (attr, value) in attribute_value_select.iteritems(): if value: expr = CompiledExpression(value, user_functions=user_functions, known_variables=known_variables) dependencies = expr.getDependencies() else: expr = None dependencies = (attr,) attributes[attr] = expr for attribute in dependencies: deps = reverse_deps.get(attribute) if deps is None: deps = set() reverse_deps[attribute] = deps deps.add(attr)
def __init__(self, parsed_viewdef, user_functions={}, new_name=None, new_parents=None, **variable_defaults): "Semantically check the view spec, compile it, store it." self.user_functions = user_functions self.view_name = new_name or parsed_viewdef.view_name self.view_parents = new_parents or parsed_viewdef.view_parents self.select_distinct = distinct = parsed_viewdef.select_distinct self.select_buckets = parsed_viewdef.select_buckets # we create new variables here to make different specs independent self.loops = [ (Variable(str(var.name)), values) for (var,values) in parsed_viewdef.loops ] self.loop_variables = [ loop[0] for loop in self.loops ] self.__all_known_variables = dict( (var,var) for var in self.loop_variables ) # compile and evaluate default values of view variables self.variable_options = {} for variable in parsed_viewdef.variable_options: if variable in self.__all_known_variables: raise AmbiguousNameError, variable if variable.name in variable_defaults: value = variable_defaults[variable.name] elif variable.default_value: val_exp = CompiledExpression(variable.default_value, user_functions=user_functions, known_variables=self.__all_known_variables) value = val_exp.evaluate() else: value = None variable = Variable(variable.name, value) self.variable_options[variable] = variable self.__all_known_variables[variable] = variable # build view interface self.view_object = ViewObjectSpec( self.view_name, parsed_viewdef.view_attributes, user_functions=user_functions, known_variables=self.__all_known_variables ) self.object_select = parsed_viewdef.object_select self.qos_statements = parsed_viewdef.qos_statements # prepare __all_attributes to collect all attribute dependencies self.__all_attributes = {} for obj in self.object_select.keys(): if obj in self.__all_known_variables: # duplicate declaration! raise AmbiguousNameError, obj self.__all_attributes[obj] = set() # compile expression for 'where' and 'having' self.where_expression = CompiledExpression( parsed_viewdef.where_expression, user_functions=user_functions, known_variables=self.__all_known_variables ) self.having_expression = CompiledExpression( parsed_viewdef.having_expression, user_functions=user_functions, known_variables=self.__all_known_variables ) # compile expressions in object selector for object_name, rank_function in self.object_select.iteritems(): if object_name in self.__all_known_variables: raise AmbiguousNameError, object_name self.__compile_rank_function(rank_function, object_name, distinct) # find and verify attribute names in created view and where expression self.__collect_attributes( self.view_object.all_dependencies() ) self.__collect_attributes( self.where_expression.getDependencies() ) self.__dependencies = tuple(sorted( chain(*self.__all_attributes.values()) )) # check dependencies of qos statements qos_attributes = set(chain(*[ st[1] for st in self.qos_statements ])) unresolved_dependencies = qos_attributes - frozenset(self.__dependencies) for unknown_attribute in unresolved_dependencies: raise UnknownReferenceError, (unknown_attribute, self.__dependencies) # compile and evaluate qos statements self.__qos_functions = {} for qos_function, qos_attributes in self.qos_statements: self.__compile_function(qos_function) for target_attribute in qos_attributes: functions = self.__qos_functions.get(target_attribute) if not functions: functions = self.__qos_functions[target_attribute] = [] functions.append(qos_function) select_string = ','.join(sorted('%s[%s]' % item for item in self.object_select.iteritems())) self.__hash = hash( (str(self.view_object), self.select_distinct, self.select_buckets, select_string, self.view_parents, self.where_expression) )
class ViewSpecification(object): """This is the compiled representation of a view specification. View specifications are guaranteed not to interfere with each other, i.e. variables and options are cloned. """ _view_functions = ViewFunctions def __init__(self, parsed_viewdef, user_functions={}, new_name=None, new_parents=None, **variable_defaults): "Semantically check the view spec, compile it, store it." self.user_functions = user_functions self.view_name = new_name or parsed_viewdef.view_name self.view_parents = new_parents or parsed_viewdef.view_parents self.select_distinct = distinct = parsed_viewdef.select_distinct self.select_buckets = parsed_viewdef.select_buckets # we create new variables here to make different specs independent self.loops = [ (Variable(str(var.name)), values) for (var,values) in parsed_viewdef.loops ] self.loop_variables = [ loop[0] for loop in self.loops ] self.__all_known_variables = dict( (var,var) for var in self.loop_variables ) # compile and evaluate default values of view variables self.variable_options = {} for variable in parsed_viewdef.variable_options: if variable in self.__all_known_variables: raise AmbiguousNameError, variable if variable.name in variable_defaults: value = variable_defaults[variable.name] elif variable.default_value: val_exp = CompiledExpression(variable.default_value, user_functions=user_functions, known_variables=self.__all_known_variables) value = val_exp.evaluate() else: value = None variable = Variable(variable.name, value) self.variable_options[variable] = variable self.__all_known_variables[variable] = variable # build view interface self.view_object = ViewObjectSpec( self.view_name, parsed_viewdef.view_attributes, user_functions=user_functions, known_variables=self.__all_known_variables ) self.object_select = parsed_viewdef.object_select self.qos_statements = parsed_viewdef.qos_statements # prepare __all_attributes to collect all attribute dependencies self.__all_attributes = {} for obj in self.object_select.keys(): if obj in self.__all_known_variables: # duplicate declaration! raise AmbiguousNameError, obj self.__all_attributes[obj] = set() # compile expression for 'where' and 'having' self.where_expression = CompiledExpression( parsed_viewdef.where_expression, user_functions=user_functions, known_variables=self.__all_known_variables ) self.having_expression = CompiledExpression( parsed_viewdef.having_expression, user_functions=user_functions, known_variables=self.__all_known_variables ) # compile expressions in object selector for object_name, rank_function in self.object_select.iteritems(): if object_name in self.__all_known_variables: raise AmbiguousNameError, object_name self.__compile_rank_function(rank_function, object_name, distinct) # find and verify attribute names in created view and where expression self.__collect_attributes( self.view_object.all_dependencies() ) self.__collect_attributes( self.where_expression.getDependencies() ) self.__dependencies = tuple(sorted( chain(*self.__all_attributes.values()) )) # check dependencies of qos statements qos_attributes = set(chain(*[ st[1] for st in self.qos_statements ])) unresolved_dependencies = qos_attributes - frozenset(self.__dependencies) for unknown_attribute in unresolved_dependencies: raise UnknownReferenceError, (unknown_attribute, self.__dependencies) # compile and evaluate qos statements self.__qos_functions = {} for qos_function, qos_attributes in self.qos_statements: self.__compile_function(qos_function) for target_attribute in qos_attributes: functions = self.__qos_functions.get(target_attribute) if not functions: functions = self.__qos_functions[target_attribute] = [] functions.append(qos_function) select_string = ','.join(sorted('%s[%s]' % item for item in self.object_select.iteritems())) self.__hash = hash( (str(self.view_object), self.select_distinct, self.select_buckets, select_string, self.view_parents, self.where_expression) ) def _multi_loop_iterator(self, loops, value_dict): if not loops: yield () else: variable, values = loops[0] variable_name = variable.name for loop_values in self._multi_loop_iterator(loops[1:], value_dict): for value in values: if hasattr(value, 'evaluate'): value = value.evaluate(value_dict) variable.value = value value_dict[variable_name] = value yield loop_values + (value,) def iter_loop_variables(self, value_dict=None): """Builds an iterator that returns one tuple for each combination of values of the loop variables. It returns () if there are no loops. The optional dictionary argument is filled with variable-value pairs. Note that these must not be changed outside the iterator.""" if value_dict is None: value_dict = {} return self._multi_loop_iterator(self.loops, value_dict) def __compile_rank_function(self, function, object_name, distinct): if function is None: return view_function_class = self._view_functions if function.name not in view_function_class.VALID_FUNCTIONS: raise UnknownReferenceError(function.name, view_function_class.VALID_FUNCTIONS) self.__compile_function(function) view_functions = view_function_class(object_name) build_function = getattr(view_functions, function.name) function.setFunction( build_function(distinct=distinct, *function.function_parameters) ) def __compile_function(self, function): parameters = [] for param in function.function_parameters: cparam = CompiledExpression(param, user_functions=self.user_functions, known_variables=self.__all_known_variables) parameters.append(cparam) self.__collect_attributes( cparam.getDependencies() ) function.function_parameters = tuple(parameters) def __collect_attributes(self, attributes): "Verify that object refences have been declared." for attribute in attributes: object_name = attribute.object_name if object_name in self.__all_known_variables: continue object_attributes = self.__all_attributes.get(object_name, None) if object_attributes is None: raise UnknownReferenceError(object_name, self.__all_attributes.keys()) else: object_attributes.add(attribute) def getDependencies(self): return self.__dependencies def getObjectDependencies(self): objects = self.__all_attributes.keys() objects.sort() return objects def getQoSParameters(self): return self.__qos_functions def __hash__(self): return self.__hash