def adapter_property(property): ''' Adapter method for additional parametes on property class ''' if property.type.name == 'multilist': raise TextXSemanticError("You can't use multilist as regular filed.") for x in property.additionalParameters: if not x.ref_param is None: if not property.ref_param is None: raise TextXSemanticError("You can't use more than one @ link.") property.ref_param = x.ref_param elif not x.params is None: if not property.params is None: raise TextXSemanticError( "You can't use more than one parameters keyword.") property.params = x.params elif not x.classes is None: if not property.classes is None: raise TextXSemanticError( "You can't use more than one class keyword.") property.classes = x.classes elif not x.ref is None: if not property.ref is None: raise TextXSemanticError( "You can't use more than one ref keyword.") property.ref = x.ref
def object_processor(object): #check if property exist for current object checkUnique = [] for fk in object.meta: for prop in fk.property.properties: if prop not in fk.object.properties: line, col = fk.object._tx_metamodel.parser.pos_to_linecol( fk.object._tx_position) raise TextXSemanticError( "ERROR: (at %d, %d) Object %s has no property named %s." % (line, col, fk.object.name, prop.name)) #check if label is unique if fk.label in checkUnique: raise TextXSemanticError( "ERROR: %s already exist. All labels in Meta must be unique." % fk.label) else: checkUnique.append(fk.label) #bind Meta to property if fk.foreignKeyType == 'list': newType = View(None, 'multilist', [], object) else: newType = View(None, 'combobox', [], object) newProperty = Property(fk.label, newType, fk.label, None, []) newProperty.dontShowInTable = True newProperty.populateFromDB = True newProperty.isMeta = True newProperty.meta_object = fk.object newProperty.extraPropertyList = fk.property.properties object.properties.append(newProperty)
def check_ScalarAttribute(a): # tests: see filebased_tests/embedded if a.is_container(): if not textx_isinstance(a.type, RawType): raise TextXSemanticError( "container {} must be an unsigned integral type.".format( a.name), **get_location(a), ) elif a.type.internaltype != "UINT": raise TextXSemanticError( "container {} must be an unsigned integral type.".format( a.name), **get_location(a), ) num_bits = reduce( lambda a, b: a + b, map( lambda a: get_bits(a.type) * get_fixed_dimension(a), a.get_container_elements(), ), ) if num_bits != get_bits(a.type): raise TextXSemanticError( "embedded elements of container {} ({}) do not sum up to {}.". format(a.name, num_bits, get_bits(a.type)), **get_location(a), )
def entity_processor(ent): """ Validates entities. """ # Check constraints for c in ent.constraints: if not c.type.applies_to_entity: raise TextXSemanticError('In Entity "{}". Constraint "{}" can not ' 'be applied to Entity.'.format( ent.name, c.type.name)) # Collect all referenced entities without other side attr name spec. referenced_entities = set() attr_names = set() for attr in children_of_type(ent, "Attribute"): if is_entity_ref(attr): if not attr.ref or not attr.ref.other_side: if id(attr_type(attr)) in referenced_entities: raise TextXSemanticError( 'In entity "{}". Multiple references to Entity "{}" ' 'without other side ' 'attr name specification. Specify other side name ' 'using "<->" syntax.'.format( parent_entity(attr).name, attr_type(attr).name)) referenced_entities.add(id(attr_type(attr))) if attr.name in attr_names: raise TextXSemanticError( 'Attribute "{}" defined more than once for' ' entity {}.'.format(attr.name, ent.name)) attr_names.add(attr.name)
def ticket_class_processor(transport_type, ticket_class): if transport_type != 'bus': if ticket_class is None: raise TextXSemanticError('Ticket class must be defined.') else: if transport_type == 'plane' and ticket_class.Class != 'economy' and ticket_class.Class != 'business': raise TextXSemanticError('Plane ticket class must be economy or business.') elif transport_type == 'train' and ticket_class.Class != 'first' and ticket_class.Class != 'second' and ticket_class.Class != 'couchette': raise TextXSemanticError('Train ticket class must be first, second or couchette.')
def check_Attribute(a): if a.name.startswith("item_"): raise TextXSemanticError( "attribute may not start with 'item_' " + a.name, **get_location(a)) if a.name.startswith("_"): raise TextXSemanticError("attribute may not start with '_' " + a.name, **get_location(a)) if hasattr(a, "type"): if a.embedded: textx_assert(a.type.name != "char", a, "char may be be used as embedded field") if hasattr(a, "type"): if textx_isinstance(a.type, RawType): if a.type.internaltype in ["INT", "UINT"] and not a.embedded: if get_bits(a.type) not in [8, 16, 32, 64, 128]: raise TextXSemanticError( "attribute {} must have a bit size of a power of two.". format(a.name), **get_location(a), ) if a.type.internaltype not in ["INT", "UINT", "BOOL" ] and a.embedded: raise TextXSemanticError( "attribute {} must be an integral type.".format(a.name), **get_location(a), ) elif textx_isinstance(a.type, get_metamodel(a)["Enum"]): if get_bits(a.type) not in [8, 16, 32, 64, 128] and not a.embedded: raise TextXSemanticError( "attribute {} must have a bit size of a power of two.". format(a.name), **get_location(a), ) # check mandatory properties in attributes mandatory_prop_defs = get_all_possible_mandatory_properties(a) attr_prop_defs = list(map(lambda p: p.definition, a.properties)) for d in mandatory_prop_defs.values(): textx_assert(d in attr_prop_defs, a, f"missing mandatory property '{d.name}'") if a.is_container(): textx_assert( a.if_attr is None, a, "restricted attributes may not be used as container (put them into a separate substruct)", ) if a.is_embedded(): textx_assert( a.if_attr is None, a, "restricted attributes may not be embedded (put them into a separate substruct)", )
def __call__(self, parser, obj, attr, obj_ref): from textx.scoping.tools import get_referenced_object, \ get_list_of_concatenated_objects from textx.scoping import Postponed try: one_def_obj = get_referenced_object(None, obj, self.path_to_definition_object, parser) def_obj_list = get_list_of_concatenated_objects( one_def_obj, self.path_to_extension, parser, []) for def_obj in def_obj_list: if type(def_obj) is Postponed: self.postponed_counter += 1 return def_obj res = get_referenced_object( None, def_obj, self.path_to_target + "." + obj_ref.obj_name, parser, obj_ref.cls) if res: return res # may be Postponed return None except TypeError as e: line, col = parser.pos_to_linecol(obj_ref.position) raise TextXSemanticError('ExtRelativeName: {}'.format(str(e)), line=line, col=col)
def selector_object_processor(selector_object): if not selector_object.property in selector_object.object.properties: raise TextXSemanticError( "object '{0}' has no attribute named '{1}'".format( selector_object.object.name, selector_object.property.name)) else: return True
def call_obj_processors(model_obj, metaclass=None): """ Depth-first model object processing. """ try: if metaclass is None: metaclass = metamodel[model_obj.__class__.__name__] except KeyError: raise TextXSemanticError('Unknown meta-class "{}".'.format( model.obj.__class__.__name__)) many = [MULT_ONEORMORE, MULT_ZEROORMORE] for metaattr in metaclass._tx_attrs.values(): # If attribute is base type or containment reference go down if metaattr.is_base_type or (metaattr.ref and metaattr.cont): attr = getattr(model_obj, metaattr.name) if attr: if metaattr.mult in many: for idx, obj in enumerate(attr): if obj: result = call_obj_processors(obj, metaattr.cls) if result is not None: attr[idx] = result else: result = call_obj_processors(attr, metaattr.cls) if result is not None: setattr(model_obj, metaattr.name, result) obj_processor = metamodel.obj_processors.get(metaclass.__name__, None) if obj_processor: return obj_processor(model_obj)
def validate_ip_range(ip_range): try: ipaddress.ip_network(ip_range.value, strict=False) except ValueError: position = SieveExpertBot.get_linecol(ip_range, as_dict=True) raise TextXSemanticError('Invalid ip range: %s.' % ip_range.value, **position)
def getUsage(self, usage): cpuUsage = {} memUsage = {} spcUsage = {} netUsage = {} for use in usage: useClass = use.__class__.__name__ if (useClass == 'CPUUsage'): cpuUsage['use'] = use.usage cpuUsage['max'] = use.max unit = 'sec' if use.unit == None else use.unit cpuUsage['interval'] = self.convertTime(use.interval, unit) elif (useClass == 'MemUsage'): unit = 'MB' if use.unit == None else use.unit memUsage['use'] = self.convertMem(use.usage, unit) elif (useClass == 'SpaceUsage'): unit = 'MB' if use.unit == None else use.unit spcUsage['use'] = self.convertMem(use.usage, unit) elif (useClass == 'NetUsage'): netUsage['rate'] = self.convertRate(use.rate, use.rateUnit) netUsage['ceil'] = 0 if use.ceil == None else self.convertRate( use.ceil, use.ceilUnit) netUsage['burst'] = 0 if use.burst == None else int(use.burst * 1024) else: raise TextXSemanticError('Unknown usage for port "%s"' % (str(use))) return { "cpu": cpuUsage, "mem": memUsage, "spc": spcUsage, "net": netUsage }
def __call__(self, obj, attr, obj_ref): from textx.scoping.tools import get_referenced_object, \ get_list_of_concatenated_objects from textx.scoping import Postponed from textx import get_model try: # print("DEBUG: ExtRelativeName.__call__(...{})". # format(obj_ref.obj_name)) one_def_obj = get_referenced_object(None, obj, self.path_to_definition_object) def_obj_list = get_list_of_concatenated_objects( one_def_obj, self.path_to_extension, []) # print("DEBUG: {}".format(def_obj_list)) for def_obj in def_obj_list: if type(def_obj) is Postponed: self.postponed_counter += 1 return def_obj res = get_referenced_object( None, def_obj, self.path_to_target + "." + obj_ref.obj_name, obj_ref.cls) if res: return res # may be Postponed return None except TypeError as e: from textx.scoping.tools import get_parser line, col = get_parser(obj).pos_to_linecol(obj_ref.position) raise TextXSemanticError('ExtRelativeName: {}'.format(str(e)), line=line, col=col, filename=get_model(obj)._tx_filename)
def validate_ip_address(ipaddr): try: ipaddress.ip_address(ipaddr.value) except ValueError: position = SieveExpertBot.get_linecol(ipaddr, as_dict=True) raise TextXSemanticError('Invalid ip address: %s.' % ipaddr.value, **position)
def selector_object_processor(selector_object): if selector_object.property not in selector_object.object.properties: line, col = selector_object._tx_metamodel.parser.pos_to_linecol( selector_object._tx_position) raise TextXSemanticError("ERROR: (at %d, %d) Object %s has no property named %s." % (line, col, selector_object.object.name, selector_object.property.name)) else: return True
def _resolve_link_rule_ref(obj_ref): if obj_ref is None: return assert type(obj_ref) is ObjCrossRef, type(obj_ref) if parser.debug: parser.dprint("Resolving obj crossref: {}:{}" .format(obj_ref.cls, obj_ref.obj_name)) def _inner_resolve_link_rule_ref(cls, obj_name): """ Depth-first resolving of link rule reference. """ if cls._tx_type is RULE_ABSTRACT: for inherited in cls._tx_inh_by: result = _inner_resolve_link_rule_ref(inherited, obj_name) if result: return result elif cls._tx_type == RULE_COMMON: if id(cls) in parser._instances: objs = parser._instances[id(cls)] if obj_name in objs: return objs[obj_name] result = _inner_resolve_link_rule_ref(obj_ref.cls, obj_ref.obj_name) # Collect cross-references for textx-tools if result: if metamodel.textx_tools_support: pos_crossref_list.append( RefRulePosition(name=obj_ref.obj_name, ref_pos_start=obj_ref.position, ref_pos_end=obj_ref.position + len(result.name), def_pos_start=result._tx_position, def_pos_end=result._tx_position_end)) return result # As a fall-back search builtins if given if metamodel.builtins: if obj_ref.obj_name in metamodel.builtins: # TODO: Classes must match return metamodel.builtins[obj_ref.obj_name] line, col = parser.pos_to_linecol(obj_ref.position) raise TextXSemanticError( message='Unknown object "{}" of class "{}" at {}' .format(obj_ref.obj_name, obj_ref.cls.__name__, (line, col)), line=line, col=col, err_type=UNKNOWN_OBJ_ERROR, expected_obj_cls=obj_ref.cls)
def data_show_processor(data_show_object): data_show_kwd = ['table', 'list', 'thumbnail'] for type in data_show_kwd: if type is data_show_object.type.name: return True else: raise TextXSemanticError( "'{0}' is not avlaible. Correct keywords are 'table', 'list' or 'thumbnail'" .format(data_show_object.type))
def check_VariantMapping(mapping): mm = get_metamodel(mapping) selector_type = mapping.parent.variant_selector.ref.type if textx_isinstance(selector_type, mm["Enum"]): if not mapping.id.is_enum(): raise TextXSemanticError( "bad type (enum of type {} is expected)".format( selector_type.name), **get_location(mapping), )
def validate_numeric_match(num_match): """ Validates a numeric match expression. Checks if the event key (given on the left hand side of the expression) is of a valid type for a numeric match, according the the IntelMQ harmonization. Raises: TextXSemanticError: when the key is of an incompatible type for numeric match expressions. """ valid_types = ['Integer', 'Float', 'Accuracy', 'ASN'] position = SieveExpertBot.get_linecol(num_match.value, as_dict=True) # validate harmonization type (event key) try: type = SieveExpertBot.harmonization[num_match.key]['type'] if type not in valid_types: raise TextXSemanticError('Incompatible type: %s.' % type, **position) except KeyError: raise TextXSemanticError('Invalid key: %s.' % num_match.key, **position)
def get_container(atype): _assert_is_embedded(atype) p = atype.parent.get_prev_attr(atype) while p is not None and not p.is_container(): p = atype.parent.get_prev_attr(p) if p is None: raise TextXSemanticError( "unexpected: did not found container of embedded attribute {}". format(atype), **get_location(atype)) return p
def process_multi_numeric_match(self, key, op, value, event) -> bool: if key not in event: return False return self._numeric_multi_op_map[op](event[key], (v.value for v in value.values)) if name == 'SingleNumericValue': return self.process_numeric_operator(event[key], op, value.value) elif name == 'NumericValueList': return any(self.process_numeric_operator(event[key], op, val.value) for val in value.values) raise TextXSemanticError(f'Unhandled type: {name}')
def check_testcase(testcase): """ checks that the config used by the testcase fulfills its needs """ for need in testcase.needs: if need not in testcase.config.haves: raise TextXSemanticError( "{}: {} not found in {}.{}".format(testcase.name, need.name, testcase.scenario.name, testcase.config.name), **get_location(testcase))
def adapter_page(page): ''' Adapter method for mapping using on page fields. ''' for x in page.using: if not x.f is None: if not page.footer is None: raise TextXSemanticError( "You can't use more than one footer on page.") page.footer = x.f elif not x.m is None: if not page.menubar is None: raise TextXSemanticError( "You can't use more than one menubar on page.") page.menubar = x.m elif not x.s is None: if not page.sidebar is None: raise TextXSemanticError( "You can't use more than one sidebar on page.") page.sidebar = x.s
def attribute_processor(attr): """ Called for each attribute. """ entity = parent_of_type(attr, "Entity") if attr.multiplicity is None: # Default multiplicity is 1,1 attr.multiplicity = Multiplicity(attr, lower=1, upper=1) elif attr.multiplicity.upper is None: # If only * is given it is must be the upper limit. if attr.multiplicity.lower == '*': attr.multiplicity.lower = 0 attr.multiplicity.upper = '*' else: # Default upper multiplicity is 1 attr.multiplicity.upper = 1 # Sanity checks m = attr.multiplicity if m.lower not in [0, 1]: raise TextXSemanticError( 'Attribute "{}". Lower bound must be 0 or 1.'.format(attr.name)) if type(m.upper) is int and m.upper != 1: raise TextXSemanticError( 'Attribute "{}". Upper bound must be 1 or *.'.format(attr.name)) if m.upper == '*' and attr.id: raise TextXSemanticError('Attribute "{}". Key attributes can\'t have ' '* multiplicity.'.format(attr.name)) if not is_entity_ref(attr) and m.upper == '*': raise TextXSemanticError( 'Attribute "{}". Can\'t use ' '* multiplicity for non-reference type.'.format(attr.name)) # Check constraints for c in attr.constraints: if not c.type.applies_to_attribute: raise TextXSemanticError('In "{}.{}". Constraint "{}" can not ' 'be applied to attribute.'.format( entity.name, attr.name, c.type.name))
def date_format_processor(date): date = date.replace('.', '/') day = date.split('/')[0] month = date.split('/')[1] year = date.split('/')[2] try: datetime.date(year=int(year), month=int(month), day=int(day)) return datetime.datetime.strptime(date, '%d/%m/%Y').strftime('%Y-%m-%d') except: raise TextXSemanticError('Departure or return date is not valid.')
def getInstances(self, instances): res = {} for inst in instances: if inst.name in res: raise TextXSemanticError('Instance name "%s" is not unique.' % inst.name) instObj = { "type": inst.type.name, } instObj["actuals"] = self.getActuals(inst.actuals) res[inst.name] = instObj return res
def page_processor(page): #Default layout je border if not page.layout: page.layout = Layout('border', ['top', 'bottom', 'center', 'left', 'right'], None) for view_on_page in page.views: if not view_on_page.position in page.layout.positions: raise TextXSemanticError( "Position '{0}' is not supported by {1} layout".format( view_on_page.position, page.layout.name))
def getComponents(self, components): res = {} for comp in components: if comp.appComponent: if comp.name in res: raise TextXSemanticError( 'Component name "%s" is not unique.' % comp.name) compObj = {} compObj["name"] = comp.name compObj["formals"] = self.getFormals(comp.formals) compObj["ports"] = self.getPorts(comp.ports) res[comp.name] = compObj return res
def validate_user_classes(self): """ Validates user classes of the meta model. Called after construction of the main metamodel (not imported ones). """ from textx.exceptions import TextXSemanticError for user_class in self.user_classes.values(): if user_class.__name__ not in self._used_rule_names_for_user_classes: # It is not a user class used in the grammar raise TextXSemanticError( "{} class is not used in the grammar".format( user_class.__name__))
def actor_obj_processor(actor): localMessages = actor.locals localMessageNames = set( [localMessage.name for localMessage in localMessages]) internalMessages = actor.internals internalMessageNames = set( [internalMessage.name for internalMessage in internalMessages]) sharedMessageNames = localMessageNames.intersection(internalMessageNames) if len(sharedMessageNames) != 0: raise TextXSemanticError( '%s: Actor local and internal messages must be distinct - shared: %r' % (actor.name, sharedMessageNames)) else: actor._messageNames = localMessageNames.union(internalMessageNames)
def query_processor(query): if not query.condition is None: query.condition.conditionName = adapter_for_query(query) for query in query.parent.queries: if (not hasattr(query, 'property')) and ( query.sortBy not in query.parent.properties): line, col = query.parent._tx_metamodel.parser.pos_to_linecol( object._tx_position) raise TextXSemanticError( "ERROR: (at %d, %d) Object %s has no property named %s." % (line, col, query.parent.object.name, query.parent.property.name)) elif (not hasattr(query, 'sortBy')) and ( query.sortBy not in query.parent.properties): line, col = query.parent._tx_metamodel.parser.pos_to_linecol( object._tx_position) raise TextXSemanticError( "ERROR: (at %d, %d) Object %s has no property named %s." % (line, col, query.parent.object.name, query.parent.property.name)) else: return True