def question_type_object_processor(question_type): """Checks if names of parameters in a question type are unique and if template path is empty. Also checks if the name of a question type is the same as the predefined question type.""" if question_type.template_path == '': raise TextXSemanticError( 'Template path for a question type can not be empty!') builtin_question_types = [ 'TextQuestion', 'ChoiceQuestion', 'DropDownQuestion', 'LinearScaleQuestion', 'DateQuestion', 'TimeQuestion', 'LikertScaleQuestion', 'NumberQuestion' ] if question_type.name in builtin_question_types: raise TextXSemanticError( 'A predefined question type {} already exists!'.format( question_type.name)) parameter_names = [ parameter.name for parameter in question_type.parameters ] for parameter_name in parameter_names: if parameter_names.count(parameter_name) > 1: raise TextXSemanticError( 'Parameter with the name {} already exists in the question type {}! Names of parameters in a question type must be unique.' .format(parameter_name, question_type.name))
def property_obj_processor(property): if property.name == 'id': raise TextXSemanticError('Property name id is not allowd') if property.name != camelcase(property.name): raise TextXSemanticError( 'Property name "%s" must be in camel case notation.' % property.name) property.primitive = property.type.name in [ 'Int', 'String', 'Long', 'Double', 'Byte', 'Float', 'Boolean' ]
def product_obj_processor(product): if product.name[0].islower(): raise TextXSemanticError( 'Name "%s" must starts with upper character' % product.name) property_names = set() for property in product.properties: if property.name in property_names: raise TextXSemanticError( 'Two properties "%s" is not allowed for the same product.' % property.name) else: property_names.add(property.name)
def examples_obj_processor(examples, return_value=False): values = set() if examples.attributes.attributes[0].name != 'should': raise TextXSemanticError('First attribute must be should.') for att in examples.attributes.attributes: name = att.name if name in values: raise TextXSemanticError( 'Same Attribute name (%s) for examples is not allowed.' % name) else: values.add(name) if return_value: return values
def parameter_value_object_processor(parameter_value): """Checks if the type of the parameter value matches the defined parameter type.""" parameter_type = parameter_value.parameter.parameter_type parameter_val = parameter_value.value.value if ((parameter_type == "string[]" and (type(parameter_val).__name__ != "list" or type(parameter_val[0]).__name__ != "str")) or (parameter_type == "integer[]" and (type(parameter_val).__name__ != "list" or type(parameter_val[0]).__name__ != "int")) or (parameter_type == "float[]" and (type(parameter_val).__name__ != "list" or type(parameter_val[0]).__name__ != "float")) or (parameter_type == "boolean[]" and (type(parameter_val).__name__ != "list" or type(parameter_val[0]).__name__ != "bool")) or (parameter_type == "string" and (type(parameter_val).__name__ != "str")) or (parameter_type == "integer" and (type(parameter_val).__name__ != "int")) or (parameter_type == "float" and (type(parameter_val).__name__ != "float")) or (parameter_type == "boolean" and (type(parameter_val).__name__ != "bool"))): raise TextXSemanticError( 'The type of the parameter {} of question type {} must be {}.'. format(parameter_value.parameter.name, parameter_value.parent.type.name, parameter_type))
def check_some_semantics(model, metamodel): tag_values = request_obj_processor(model.request, True) example_values = set() for case in model.cases: tag_values = tag_values.union( response_obj_processor(case.response, True)) example_values = example_values.union( examples_obj_processor(case.examples, True)) example_values.remove('should') for tag_val in tag_values: if tag_val not in example_values: raise TextXSemanticError( 'Tag value (%s) is not present in examples.' % tag_val) for ex_val in example_values: if ex_val not in tag_values: raise TextXSemanticError( 'Tag value (%s) is not present in request nor responses.' % ex_val)
def check_request_tags(tag_values, arg): if 'TagValue' in arg.value.__class__.__name__: value = arg.value.name if value in tag_values: raise TextXSemanticError( 'Same Tag name (%s) for GraphQL arguments is not allowed.' % value) else: tag_values.add(value) elif 'CompoundValue' in arg.value.__class__.__name__: for argument in arg.value.arguments: check_request_tags(tag_values, argument)
def survey_content_object_processor(survey_content): """Checks if all question names are unique""" question_names = [] for section in survey_content.sections: question_names.extend( [question.name for question in section.questions]) for question_name in question_names: if question_names.count(question_name) > 1: raise TextXSemanticError( 'Question with the name {} already exists! Question names must be unique.' .format(question_name))
def has_property(attr, prop_name, raises_if_not_applicable=True): res = list( filter(lambda x: x.definition.name == prop_name, attr.properties)) if len(res) == 0: if (prop_name not in get_all_possible_properties(attr) and raises_if_not_applicable): raise TextXSemanticError( "{} not a possible property".format(prop_name), **get_location(attr)) return False else: assert len(res) == 1 return True
def question_object_processor(question): """Checks if all required parameters of the chosen question type are defined. Also checks if a value for a parameter has been defined more than once.""" parameters_in_question = [param.parameter for param in question.parameters] for parameter in question.type.parameters: if parameter.required == True and parameter not in parameters_in_question: raise TextXSemanticError( 'A required parameter {} of question type {} is missing from the question {}!' .format(parameter, question.type.name, question.name)) for parameter in parameters_in_question: if parameters_in_question.count(parameter) > 1: raise TextXSemanticError( 'Parameter {} of question type {} has been defined twice in question {}' .format(parameter.name, question.type.name, question.name)) # change parameters list to dictionary parameters_dict = {} for parameter in question.parameters: parameters_dict[parameter.parameter.name] = parameter.value.value question.parameters = parameters_dict
def check_response_tags(tag_values, memb_value): if 'TagValue' in memb_value.__class__.__name__: value = memb_value.name if value in tag_values: raise TextXSemanticError( 'Same Tag name (%s) for response is not allowed.' % value) else: tag_values.add(value) elif 'JsonObject' in memb_value.__class__.__name__: for member in memb_value.members: check_response_tags(tag_values, member.value) elif 'JsonArray' in memb_value.__class__.__name__: mult = memb_value.multiplier if mult is not None: if 'TagValue' in mult.value.__class__.__name__: value = mult.value.name if value in tag_values: raise TextXSemanticError( 'Same Tag name (%s) for response is not allowed.' % value) else: tag_values.add(value) for value in memb_value.values: check_response_tags(tag_values, value)
def mode_obj_processor(mode): if mode.name[0].islower(): raise TextXSemanticError( f'Mode name "{mode.name}" must be capitalized.', **get_location(mode))
def raise_semantic_error(error_msg, ast_node, model): line, col = model._tx_parser.pos_to_linecol( ast_node._tx_position) raise TextXSemanticError(error_msg, line=line, col=col)
def semantic_check(model, metamodel): if model.name == "WrongMode": raise TextXSemanticError( 'The root mode cannot be called "Wrong Mode".', **get_location(model))
def check_some_semantics(model, metamodel): if model.base_product.type != 'base': raise TextXSemanticError( 'First defined product must be "base" product.') for product in model.products: if product.type == 'base': raise TextXSemanticError( 'You must declare exactly one "base" product.') name_found = False for pr in model.base_product.properties: if pr.name == 'name': name_found = True if not name_found: raise TextXSemanticError( 'Property "name" for base product must be declared.') categories = model.categories product_set = set() category_set = set() non_product_category_set = set() for product in model.products: if product.name in product_set: raise TextXSemanticError( 'Product "%s" is defined more than once' % product.name) else: product_set.add(product.name) for category in categories: if category.name not in category_set: category_set.add(category.name) else: raise TextXSemanticError( 'Category "%s" is defined more than once' % category.name) if category.name in product_set: product_set.add(category.name) else: if category.name not in non_product_category_set: non_product_category_set.add(category.name) else: non_product_category_set.add(category.name) non_product_category_map = {} for cat in non_product_category_set: non_product_category_map[cat] = False for category in categories: if category.name not in product_set and category.subcategory is not None and category.subcategory.name in product_set: raise TextXSemanticError( 'Category "%s" must be on the end of inheritance level.' % category.subcategory.name) if category.subcategory is not None and category.subcategory.name in non_product_category_map: non_product_category_map[category.subcategory.name] = True if category.name in product_set and category.subcategory.name in product_set: raise TextXSemanticError( 'One product category can not inherit another product category.' ) for category in non_product_category_map: if not non_product_category_map[category]: raise TextXSemanticError( 'Category "%s" must not be on the end of inheritance level.' % category) for product in product_set: if product not in category_set: raise TextXSemanticError('Category "%s" must be declared.' % product) base_properties = set() for pr in model.base_product.properties: base_properties.add(pr.name) for product in model.products: for pr in product.properties: if pr.name in base_properties: raise TextXSemanticError( 'Property "%s" is defined in base and in inherited product.' % pr.name)
def check_flow(f): if f.algo1.outp != f.algo2.inp: raise TextXSemanticError("algo data types must match", **tools.get_location(f))
def category_obj_processor(category): if category.name[0].islower(): raise TextXSemanticError( 'Name "%s" must starts with upper character' % category.name)