def test_create_missing_types__raises_error_if_primary_type_is_missing( self): # -- HINT: primary type is not provided in type_dict (existing_types) existing_types = {} for schema, missing_types in self.SPECIAL_FIELD_TYPES_DATA: with self.assertRaises(MissingTypeError): Parser.create_missing_types(schema, existing_types)
def test_create_missing_types__if_special_types_exist(self): existing_types = dict(Number=parse_number) for schema, missing_types in self.SPECIAL_FIELD_TYPES_DATA: # -- FIRST STEP: Prepare new_types = Parser.create_missing_types(schema, existing_types) self.assertGreater(len(new_types), 0) # -- SECOND STEP: Now all needed special types should exist. existing_types2 = existing_types.copy() existing_types2.update(new_types) new_types2 = Parser.create_missing_types(schema, existing_types2) self.assertEqual(len(new_types2), 0)
def __call__(self, step_text, step_impl): try: parser = Parser(step_impl.pattern, parsetype_registry.types) except ValueError: raise Exception("Cannot create parser") # raise StepPatternError(step_impl.pattern, func.__name__, e) match = parser.search(step_text, evaluate_result=False) if match: return self.Match(match), len(match.match.group()) return None, 0
def test_create_missing_types__without_cardinality_fields_in_schema(self): schemas = ["{}", "{:Number}", "{number3}", "{number4:Number}", "XXX"] existing_types = {} for schema in schemas: new_types = Parser.create_missing_types(schema, existing_types) self.assertEqual(len(new_types), 0) self.assertEqual(new_types, {})
def test_parse_step_arguments_object(parse_pattern, string, expected_args, expected_kwargs): """ Test functionality of ParseStepArguments object """ # given parser = Parser(parse_pattern) match = parser.search(string, evaluate_result=False) args = matcher.ParseStepArguments(match) # when actual_args, actual_kwargs = args.evaluate() # then assert actual_args == expected_args assert actual_kwargs == expected_kwargs
def match_step(sentence, steps): """ Tries to find a match from the given sentence with the given steps :param string sentence: the step sentence to match :param dict steps: the available registered steps :returns: the arguments and the func which were matched :rtype: tuple """ potentional_matches = [] for pattern, func in steps.items(): if isinstance(pattern, re_pattern): # pylint: disable=protected-access match = pattern.search(sentence) argument_match = RegexStepArguments(match) if match: longest_group = get_longest_group(match) else: longest_group = 0 else: try: parser = Parser(pattern, CustomTypeRegistry().custom_types) except ValueError as e: raise StepPatternError(pattern, func.__name__, e) match = parser.search(sentence, evaluate_result=False) argument_match = ParseStepArguments(match) if match: longest_group = get_longest_group(match.match) else: longest_group = 0 if match: step_match = StepMatch(argument_match=argument_match, func=func) if len(sentence) == longest_group: # if perfect match can be made we return it no # matter of the other potentional matches return step_match distance_to_perfect = abs(len(sentence) - longest_group) potentional_matches.append((step_match, distance_to_perfect)) if potentional_matches: # get best match return min(potentional_matches, key=lambda x: x[1])[0] return None
def match_step(sentence, steps): """ Tries to find a match from the given sentence with the given steps :param string sentence: the step sentence to match :param dict steps: the available registered steps :returns: the arguments and the func which were matched :rtype: tuple """ potentional_matches = [] for pattern, func in steps.items(): if isinstance(pattern, re._pattern_type): # pylint: disable=protected-access match = pattern.search(sentence) argument_match = RegexStepArguments(match) if match: longest_group = get_longest_group(match) else: longest_group = 0 else: try: parser = Parser(pattern, CustomTypeRegistry().custom_types) except ValueError as e: raise StepPatternError(pattern, func.__name__, e) match = parser.search(sentence, evaluate_result=False) argument_match = ParseStepArguments(match) if match: longest_group = get_longest_group(match.match) else: longest_group = 0 if match: step_match = StepMatch(argument_match=argument_match, func=func) if len(sentence) == longest_group: # if perfect match can be made we return it no # matter of the other potentional matches return step_match distance_to_perfect = abs(len(sentence) - longest_group) potentional_matches.append((step_match, distance_to_perfect)) if potentional_matches: # get best match return min(potentional_matches, key=lambda x: x[1])[0] return None
def test_parser__can_parse_normal_fields(self): existing_types = dict(Number=parse_number) schema = "Number: {number:Number}" parser = Parser(schema, existing_types) self.assert_match(parser, "Number: 42", "number", 42) self.assert_match(parser, "Number: 123", "number", 123) self.assert_mismatch(parser, "Number: ") self.assert_mismatch(parser, "Number: XXX") self.assert_mismatch(parser, "Number: -123")
def test_parser__can_parse_cardinality_field_optional(self): # -- CARDINALITY: 0..1 = zero_or_one = optional existing_types = dict(Number=parse_number) self.assertFalse("Number?" in existing_types) # -- ENSURE: Missing type variant is created. schema = "OptionalNumber: {number:Number?}" parser = Parser(schema, existing_types) self.assertTrue("Number?" in existing_types) # -- ENSURE: Newly created type variant is usable. self.assert_match(parser, "OptionalNumber: 42", "number", 42) self.assert_match(parser, "OptionalNumber: 123", "number", 123) self.assert_match(parser, "OptionalNumber: ", "number", None) self.assert_mismatch(parser, "OptionalNumber:") self.assert_mismatch(parser, "OptionalNumber: XXX") self.assert_mismatch(parser, "OptionalNumber: -123")
def test_parser__can_parse_cardinality_field_many0(self): # -- CARDINALITY: 0..* = zero_or_more = many0 existing_types = dict(Number=parse_number) self.assertFalse("Number*" in existing_types) # -- ENSURE: Missing type variant is created. schema = "List0: {numbers:Number*}" parser = Parser(schema, existing_types) self.assertTrue("Number*" in existing_types) # -- ENSURE: Newly created type variant is usable. self.assert_match(parser, "List0: 42", "numbers", [42]) self.assert_match(parser, "List0: 1, 2, 3", "numbers", [1, 2, 3]) self.assert_match(parser, "List0: ", "numbers", []) self.assert_mismatch(parser, "List0:") self.assert_mismatch(parser, "List0: XXX") self.assert_mismatch(parser, "List0: -123")
def test_parser__can_parse_cardinality_field_many_with_own_type_builder( self): # -- CARDINALITY: 1..* = one_or_more = many class MyCardinalityFieldTypeBuilder(CardinalityFieldTypeBuilder): listsep = ';' type_builder = MyCardinalityFieldTypeBuilder existing_types = dict(Number=parse_number) self.assertFalse("Number+" in existing_types) # -- ENSURE: Missing type variant is created. schema = "List: {numbers:Number+}" parser = Parser(schema, existing_types, type_builder) self.assertTrue("Number+" in existing_types) # -- ENSURE: Newly created type variant is usable. # NOTE: Use other list separator. self.assert_match(parser, "List: 42", "numbers", [42]) self.assert_match(parser, "List: 1; 2; 3", "numbers", [1, 2, 3]) self.assert_match(parser, "List: 4;5;6", "numbers", [4, 5, 6]) self.assert_mismatch(parser, "List: ") self.assert_mismatch(parser, "List:") self.assert_mismatch(parser, "List: XXX") self.assert_mismatch(parser, "List: -123")
def test_create_missing_types__if_special_types_are_missing(self): existing_types = dict(Number=parse_number) for schema, missing_types in self.SPECIAL_FIELD_TYPES_DATA: new_types = Parser.create_missing_types(schema, existing_types) self.assertSequenceEqual(set(new_types.keys()), set(missing_types))
def test_create_missing_types__raises_error_if_primary_type_is_missing(self): # -- HINT: primary type is not provided in type_dict (existing_types) existing_types = {} for schema, missing_types in self.SPECIAL_FIELD_TYPES_DATA: with self.assertRaises(MissingTypeError): Parser.create_missing_types(schema, existing_types)