def _validate_content(self, content, node: Node): if node.content is None or type(node.content) is not str: msg = f'Node "{node.name}" content should be type "{TYPE_STR}", not "{type(node.content)}"' raise MetapypeRuleError(msg) if node.content not in PERMISSIONS: msg = f'Node "{node.name}" content should be one of "{PERMISSIONS}", not "{node.content}"' raise MetapypeRuleError(msg)
def _validate_content(self, content, node: Node): if node.content is not None and type(node.content) is not str: msg = f'Node "{node.name}" content should be type "{TYPE_STR}", not "{type(node.content)}"' raise MetapypeRuleError(msg) if len(node.children) == 0 and node.content is None: msg = f'Node "{node.name}" content should not be empty' raise MetapypeRuleError(msg)
def _validate_attributes(self, node: Node, errs: list = None) -> None: """ Validates node attributes for rule compliance. Iterates through the dict of attribute rules and validates whether the node instance complies with the rule. Args: node: Node instance to be validated Returns: None Raises: MetapypeRuleError: Illegal attribute or missing required attribute """ for attribute in self._attributes: required = self._attributes[attribute][0] # Test for required attributes if required and attribute not in node.attributes: msg = f'"{attribute}" is a required attribute of node "{node.name}"' if errs is None: raise MetapypeRuleError(msg) else: errs.append(( ValidationError.ATTRIBUTE_REQUIRED, msg, node, attribute, )) for attribute in node.attributes: # Test for non-allowed attribute if attribute not in self._attributes: msg = f'"{attribute}" is not a recognized attribute of node "{node.name}"' if errs is None: raise MetapypeRuleError(msg) else: errs.append(( ValidationError.ATTRIBUTE_UNRECOGNIZED, msg, node, attribute, )) else: # Test for enumerated list of allowed values if (len(self._attributes[attribute]) > 1 and node.attributes[attribute] not in self._attributes[attribute][1:]): msg = f'Node "{node.name}" attribute "{attribute}" must be one of the following: "{self._attributes[attribute][1:]}"' if errs is None: raise MetapypeRuleError(msg) else: errs.append(( ValidationError.ATTRIBUTE_EXPECTED_ENUM, msg, node, attribute, self._attributes[attribute][1:], ))
def _validate_str_content(node: Node, errs: list = None): if node.content is not None and type(node.content) is not str: msg = f'Node "{node.name}" content should be type "{TYPE_STR}", not "{type(node.content)}"' if errs is None: raise MetapypeRuleError(msg) else: errs.append(( ValidationError.CONTENT_EXPECTED_STRING, msg, node, type(node.content), )) if node.content is not None: try: node.content.encode(encoding="utf-8", errors="strict") except UnicodeError as ex: msg = f'Node "{node.name}" content contains non-unicode character(s)' if errs is None: raise StrContentUnicodeError(msg) else: errs.append(( ValidationError.CONTENT_EXPECTED_STRING, msg, node, type(node.content), ))
def validate_children(children: list, node: Node) -> None: """ Validates node children for rule compliance. Iterates through the list children rules and validates whether the node instance complies with the rules. Args: children: list of lists containing children node: Node instance to be validated Returns: None Raises: MetapypeRuleError: Illegal child, bad sequence or choice, missing child, or wrong child cardinality """ i = 0 max_i = len(node.children) for child in children: name = child[:-2] min = child[-2] max = child[-1] cnt = 0 while i < max_i: child_name = node.children[i].name if child_name in name: cnt += 1 if max is not INFINITY and cnt > max: msg = f'Maximum occurrence of "{name}" exceeded for "{node.name}"' raise MetapypeRuleError(msg) i += 1 else: break if cnt < min: msg = f'Minimum occurrence of "{name}" not met for "{node.name}"' raise MetapypeRuleError(msg) if i < max_i: child_name = node.children[i].name msg = f'Child "{child_name}" not allowed for "{node.name}"' raise MetapypeRuleError(msg)
def _validate_non_empty_content(node: Node, is_mixed_content: bool, errs: list = None): if node.content is None or len(str(node.content)) == 0: if (is_mixed_content and len(node.children) == 0) or not is_mixed_content: msg = f'Node "{node.name}" content should not be empty' if errs is None: raise MetapypeRuleError(msg) else: errs.append( (ValidationError.CONTENT_EXPECTED_NONEMPTY, msg, node))
def _validate_empty_content(node: Node, errs: list = None): if node.content is not None: msg = f'Node "{node.name}" content should be empty' if errs is None: raise MetapypeRuleError(msg) else: errs.append(( ValidationError.CONTENT_EXPECTED_EMPTY, msg, node, node.content, ))
def _validate_time_content(node: Node, errs: list = None): val = node.content if val is not None and not Rule.is_time(val): msg = f'Node "{node.name}" format should be time ("HH:MM:SS" or "HH:MM:SS.f")' if errs is None: raise MetapypeRuleError(msg) else: errs.append(( ValidationError.CONTENT_EXPECTED_TIME_FORMAT, msg, node, node.content, ))
def _validate_float_content(node: Node, errs: list = None): val = node.content if val is not None and not Rule.is_float(val): msg = f'Node "{node.name}" content should be type "{TYPE_FLOAT}", not "{type(node.content)}"' if errs is None: raise MetapypeRuleError(msg) else: errs.append(( ValidationError.CONTENT_EXPECTED_FLOAT, msg, node, type(node.content), ))
def _validate_yeardate_content(node: Node, errs: list = None): val = node.content if val is not None and not Rule.is_yeardate(val): msg = f'Node "{node.name}" format should be year ("YYYY") or date ("YYYY-MM-DD")' if errs is None: raise MetapypeRuleError(msg) else: errs.append(( ValidationError.CONTENT_EXPECTED_YEAR_FORMAT, msg, node, node.content, ))
def validate_attributes(attributes: dict, node: Node) -> None: """ Validates node attributes for rule compliance. Iterates through the dict of attribute rules and validates whether the node instance complies with the rule. Args: attributes: dict of rule attributes node: Node instance to be validates Returns: None Raises: MetapypeRuleError: Illegal attribute or missing required attribute """ for attribute in attributes: required = attributes[attribute][0] # Test for required attributes if required and attribute not in node.attributes: msg = ( f'"{attribute}" is a required attribute of node "{node.name}"' ) raise MetapypeRuleError(msg) for attribute in node.attributes: # Test for non-allowed attribute if attribute not in attributes: msg = f'"{attribute}" is not a recognized attributes of node "{node.name}"' raise MetapypeRuleError(msg) else: # Test for enumerated list of allowed values if ( len(attributes[attribute]) > 1 and node.attributes[attribute] not in attributes[attribute][1:] ): msg = f'Node "{node.name}" attribute "{attribute}" must be one of the following: "{attributes[attribute][1:]}"' raise MetapypeRuleError(msg)
def _validate_enum_content(node: Node, enum_values: list, errs: list = None): if node.content not in enum_values: msg = f'Node "{node.name}" content should be one of "{enum_values}", not "{node.content}"' if errs is None: raise MetapypeRuleError(msg) else: errs.append(( ValidationError.CONTENT_EXPECTED_ENUM, msg, node, enum_values, node.content, ))
def _validate_float_nonnegative(self, node: Node, errs: list = None): self._validate_float_content(node, errs) float_val = float(node.content) if float_val < 0: msg = f'Node "{node.name}" content should be non-negative' if errs is None: raise MetapypeRuleError(msg) else: errs.append(( ValidationError.CONTENT_EXPECTED_RANGE, msg, node, 0, None, float_val, ))
def _validate_float_range_content(self, node: Node, minmax, errs: list = None): self._validate_float_content(node, errs) float_val = float(node.content) if float_val < minmax[0] or float_val > minmax[1]: msg = f'Node "{node.name}" content should be in range {minmax}' if errs is None: raise MetapypeRuleError(msg) else: errs.append(( ValidationError.CONTENT_EXPECTED_RANGE, msg, node, minmax[0], minmax[1], float_val, ))
def _validate_content(self, content, node: Node): if node.content is not None: msg = f'Node "{node.name}" content should be empty' raise MetapypeRuleError(msg)
def child_list_max_occurrences(child_list: list): if list is None or len(child_list) < 3: raise MetapypeRuleError( "Child list must contain at least 3 elements") max_occurrences = child_list[-1] return max_occurrences
def child_list_node_names(child_list: list): if list is None or len(child_list) < 3: raise MetapypeRuleError( "Child list must contain at least 3 elements") node_names = child_list[:-2] return node_names