def test_strip_space_from_description(self): test_cases = [ ( [ '{d} first line of description', 'second line of description {d}', 'instruction line' ], Expectation( asrt.equals( 'first line of description\nsecond line of description' ), assert_instruction(3, 'instruction line'), assert_source(is_at_eof=asrt.equals(True), has_current_line=asrt.equals(False))), ), ( [ '{d}', 'first line of description', ' second line of description', '', '{d}', 'instruction source' ], Expectation( asrt.equals( 'first line of description\n second line of description' ), assert_instruction(6, 'instruction source'), assert_source(is_at_eof=asrt.equals(True), has_current_line=asrt.equals(False))), ), ] for source_lines, expectation in test_cases: with self.subTest(source_lines=str(source_lines)): check(self, expectation, Arrangement(self.sut, _source_of_lines(source_lines)))
def test_parse(self): pattern = 'include*' space = ' ' cases = [ SourceCase('single name argument', remaining_source(name_glob_pattern_matcher_of(pattern)), assert_source(is_at_eof=asrt.is_true), ), SourceCase('single name argument followed by space, and following lines', remaining_source(name_glob_pattern_matcher_of(pattern) + space, ['following line']), assert_source(current_line_number=asrt.equals(1), remaining_part_of_current_line=asrt.equals(space[1:])), ), SourceCase('single name argument followed by arguments', remaining_source(name_glob_pattern_matcher_of(pattern) + space + 'following argument', ['following line']), assert_source(current_line_number=asrt.equals(1), remaining_part_of_current_line=asrt.equals(space[1:] + 'following argument')), ), ] for case in cases: with self.subTest(case=case.name): self._check_parse( case.source, Expectation( resolved_value_equals_file_matcher(file_matchers.FileMatcherNameGlobPattern(pattern)), source=case.source_assertion, ) )
def test_strip_space_from_description(self): test_cases = [ (['\' first line of description', 'second line of description \'', 'instruction line'], Expectation(asrt.equals('first line of description\nsecond line of description'), assert_instruction(3, 'instruction line'), assert_source(is_at_eof=asrt.equals(True), has_current_line=asrt.equals(False))), ), (['\'', 'first line of description', ' second line of description', '', '\'', 'instruction source'], Expectation(asrt.equals('first line of description\n second line of description'), assert_instruction(6, 'instruction source'), assert_source(is_at_eof=asrt.equals(True), has_current_line=asrt.equals(False))), ), ] for source_lines, expectation in test_cases: with self.subTest(source_lines=str(source_lines)): check(self, expectation, Arrangement(self.sut, source_of_lines(source_lines)))
def test_valid_token(self): test_cases = [ ('token', assert_plain('token'), assert_source(is_at_eol=asrt.is_true, has_current_line=asrt.is_true, current_line_number=asrt.equals(1))), (' token_preceded_by_space', assert_plain('token_preceded_by_space'), assert_source(is_at_eol=asrt.is_true, has_current_line=asrt.is_true, current_line_number=asrt.equals(1))), ('token_followed_by_space ', assert_plain('token_followed_by_space'), source_is_not_at_end( remaining_part_of_current_line=asrt.equals(' '), current_line_number=asrt.equals(1))), ('token_followed_by_other_token other_token', assert_plain('token_followed_by_other_token'), source_is_not_at_end( remaining_part_of_current_line=asrt.equals(' other_token'), current_line_number=asrt.equals(1))), ('<<->> other_token', assert_plain('<<->>'), source_is_not_at_end( remaining_part_of_current_line=asrt.equals(' other_token'), current_line_number=asrt.equals(1))), ('\'single quoted\'', assert_quoted('single quoted', '\'single quoted\''), assert_source(is_at_eol=asrt.is_true, has_current_line=asrt.is_true, current_line_number=asrt.equals(1))), ('\"double quoted\"', assert_quoted('double quoted', '\"double quoted\"'), assert_source(is_at_eol=asrt.is_true, has_current_line=asrt.is_true, current_line_number=asrt.equals(1))), (' \'quoted preceded by space\'', assert_quoted('quoted preceded by space', '\'quoted preceded by space\''), assert_source(is_at_eol=asrt.is_true, has_current_line=asrt.is_true, current_line_number=asrt.equals(1))), (' \'quoted followed by space\' ', assert_quoted('quoted followed by space', '\'quoted followed by space\''), source_is_not_at_end( remaining_part_of_current_line=asrt.equals(' '), current_line_number=asrt.equals(1))), (' \'quoted token followed by other token\' \'other_token\'', assert_quoted('quoted token followed by other token', '\'quoted token followed by other token\''), source_is_not_at_end(remaining_part_of_current_line=asrt.equals( ' \'other_token\''), current_line_number=asrt.equals(1))), ] for first_line, token_assertion, source_assertion in test_cases: with self.subTest(msg=repr(first_line)): source = remaining_source(first_line) actual = sut.parse_token_on_current_line(source) token_assertion.apply_with_message(self, actual, 'token') source_assertion.apply_with_message(self, source, 'source')
def test_valid_token(self): test_cases = [ ('token', assert_plain('token'), assert_source(is_at_eol=asrt.is_true, has_current_line=asrt.is_true, current_line_number=asrt.equals(1))), (' token_preceded_by_space', assert_plain('token_preceded_by_space'), assert_source(is_at_eol=asrt.is_true, has_current_line=asrt.is_true, current_line_number=asrt.equals(1))), ('token_followed_by_space ', assert_plain('token_followed_by_space'), source_is_not_at_end(remaining_part_of_current_line=asrt.equals(' '), current_line_number=asrt.equals(1))), ('token_followed_by_other_token other_token', assert_plain('token_followed_by_other_token'), source_is_not_at_end(remaining_part_of_current_line=asrt.equals(' other_token'), current_line_number=asrt.equals(1))), ('<<->> other_token', assert_plain('<<->>'), source_is_not_at_end(remaining_part_of_current_line=asrt.equals(' other_token'), current_line_number=asrt.equals(1))), ('\'single quoted\'', assert_quoted('single quoted', '\'single quoted\''), assert_source(is_at_eol=asrt.is_true, has_current_line=asrt.is_true, current_line_number=asrt.equals(1))), ('\"double quoted\"', assert_quoted('double quoted', '\"double quoted\"'), assert_source(is_at_eol=asrt.is_true, has_current_line=asrt.is_true, current_line_number=asrt.equals(1))), (' \'quoted preceded by space\'', assert_quoted('quoted preceded by space', '\'quoted preceded by space\''), assert_source(is_at_eol=asrt.is_true, has_current_line=asrt.is_true, current_line_number=asrt.equals(1))), (' \'quoted followed by space\' ', assert_quoted('quoted followed by space', '\'quoted followed by space\''), source_is_not_at_end(remaining_part_of_current_line=asrt.equals(' '), current_line_number=asrt.equals(1))), (' \'quoted token followed by other token\' \'other_token\'', assert_quoted('quoted token followed by other token', '\'quoted token followed by other token\''), source_is_not_at_end(remaining_part_of_current_line=asrt.equals(' \'other_token\''), current_line_number=asrt.equals(1))), ] for first_line, token_assertion, source_assertion in test_cases: with self.subTest(msg=repr(first_line)): source = remaining_source(first_line) actual = sut.parse_token_on_current_line(source) token_assertion.apply_with_message(self, actual, 'token') source_assertion.apply_with_message(self, source, 'source')
def test_no_token_on_remaining_part_of_current_line(self): test_cases = [ '', ' ', ] for first_line in test_cases: with self.subTest(msg=repr(first_line)): source = remaining_source(first_line) actual = sut.parse_token_or_none_on_current_line(source) self.assertIsNone(actual) assert_source(is_at_eol=asrt.is_true)
def test_no_token_on_remaining_part_of_current_line(self): test_cases = [ '', ' ', ] for first_line in test_cases: with self.subTest(msg=repr(first_line)): source = remaining_source(first_line) actual = sut.parse_token_or_none_on_current_line(source) self.assertIsNone(actual) assert_source(is_at_eol=asrt.is_true)
def _source_variants_with__for_expression_parser() -> List[Tuple[Arguments, ValueAssertion[ParseSource]]]: space = ' ' following_argument = 'argumentOfOthers' return [ (Arguments('', []), asrt_source.source_is_at_end), (Arguments(space, ['following line']), asrt_source.assert_source(current_line_number=asrt.equals(1), remaining_part_of_current_line=asrt.equals(space[1:]))), (Arguments(space + following_argument, [' ']), asrt_source.assert_source(current_line_number=asrt.equals(1), remaining_part_of_current_line=asrt.equals(space[1:] + following_argument))), ]
def test_failing_validation(self): # ARRANGE # symbol_not_an_int = StringSymbolContext.of_constant('SYMBOL_NOT_AN_INT', 'notAnInt') cases = [ ValidationCase(comparators.EQ.name + ' not a number', remaining_source(comparators.EQ.name + ' notANumber'), source_assertion= assert_source(is_at_eol=asrt.is_true), ), ValidationCase(comparators.EQ.name + ' not an int', remaining_source(comparators.EQ.name + ' 0.5'), source_assertion= assert_source(is_at_eol=asrt.is_true), ), ValidationCase(comparators.EQ.name + ' invalid expression syntax', remaining_source(comparators.EQ.name + ' (1'), source_assertion= assert_source(is_at_eol=asrt.is_true), ), ValidationCase(comparators.EQ.name + ' with symbol references', remaining_source( '== {}'.format(symbol_reference_syntax_for_name(symbol_not_an_int.name)) ), source_assertion= assert_source(is_at_eol=asrt.is_true), references=asrt.matches_singleton_sequence( symbol_not_an_int.reference_assertion__string__w_all_indirect_refs_are_strings), symbols=symbol_not_an_int.symbol_table ), ] for case in cases: with self.subTest(case.name): integration_check.CHECKER__PARSE_SIMPLE.check( self, case.source, input_=integration_check.ARBITRARY_MODEL, arrangement=arrangement_wo_tcds( symbols=case.symbols, ), expectation=Expectation( ParseExpectation( source=case.source_assertion, symbol_references=case.references, ), ExecutionExpectation( validation=validation.ValidationAssertions.pre_sds_fails__w_any_msg(), ), ) )
def test_consume__consume_all_characters_of_current_line_plus_one(self): test_cases = [ ('first line\nsecond line', assert_source(is_at_eof=asrt.is_false, has_current_line=asrt.is_true, is_at_eol=asrt.is_false, is_at_eol__except_for_space=asrt.is_false, current_line_number=asrt.equals(2), current_line_text=asrt.equals('second line'), column_index=asrt.equals(0), remaining_source=asrt.equals('second line')) ), ('single line\n', assert_source(is_at_eof=asrt.is_true, has_current_line=asrt.is_true, is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, current_line_number=asrt.equals(2), current_line_text=asrt.equals(''), column_index=asrt.equals(0), remaining_source=asrt.equals('')) ), ('\n', assert_source(is_at_eof=asrt.is_true, has_current_line=asrt.is_true, is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, current_line_number=asrt.equals(2), current_line_text=asrt.equals(''), column_index=asrt.equals(0), remaining_source=asrt.equals('')) ), ('\nsecond line', assert_source(is_at_eof=asrt.is_false, has_current_line=asrt.is_true, is_at_eol=asrt.is_false, is_at_eol__except_for_space=asrt.is_false, current_line_number=asrt.equals(2), current_line_text=asrt.equals('second line'), column_index=asrt.equals(0), remaining_source=asrt.equals('second line')) ), ] for source_string, expectation in test_cases: with self.subTest(msg='consume len(current line)+1: ' + repr(source_string)): source = ParseSource(source_string) source.consume(1 + len(source.current_line_text)) expectation.apply_with_message(self, source, 'consume len(current line)+1:{}'.format(repr(source_string)))
def test_document_is_not_mandatory_and_not_present(self): some_white_space = ' ' source_cases = [ ([ '', ], asrt_source.is_at_end_of_line(1)), ([ some_white_space, ], asrt_source.assert_source( current_line_number=asrt.equals(1), remaining_part_of_current_line=asrt.equals(some_white_space)) ), ([ '', 'line after', ], asrt_source.is_at_end_of_line(1)), ] parser = sut.HereDocParser(False) for source_lines, source_assertion in source_cases: with self.subTest(msg=repr((source_lines, source_assertion))): source = remaining_source_lines(source_lines) actual = parser.parse(source) self.assertIsNone(actual, 'return value from parsing') source_assertion.apply_with_message(self, source, 'source')
def _source_variants_with__for_expression_parser( num_expression_lines: int = 1 ) -> List[Tuple[Arguments, Assertion[ParseSource]]]: space = ' ' following_argument = 'argumentOfOthers' return [ (Arguments('', []), asrt_source.is_at_end_of_line(num_expression_lines)), (Arguments(space, ['following line']), asrt_source.assert_source( current_line_number=asrt.equals(num_expression_lines), remaining_part_of_current_line=asrt.equals(space[1:]))), (Arguments(space + following_argument, [' ']), asrt_source.assert_source( current_line_number=asrt.equals(num_expression_lines), remaining_part_of_current_line=asrt.equals(space[1:] + following_argument))), ]
def test_symbol_references(self): file_to_interpret = fs.File('python-program.py', python_program_that_exits_with_code_given_as_first_cl_arg) file_to_interpret_symbol = NameAndValue('file_to_interpret_symbol', file_to_interpret.file_name) python_interpreter_symbol = NameAndValue('python_interpreter_symbol', sys.executable) exit_code_symbol = NameAndValue('exit_code_symbol', 72) argument = ' {python_interpreter} {interpret_option} {file_to_interpret} "{exit_code}"'.format( python_interpreter=symbol_reference_syntax_for_name(python_interpreter_symbol.name), interpret_option=args.option(syntax_elements.EXISTING_FILE_OPTION_NAME).as_str, file_to_interpret=symbol_reference_syntax_for_name(file_to_interpret_symbol.name), exit_code=symbol_reference_syntax_for_name(str(exit_code_symbol.name)), ) following_line = 'following line' source = remaining_source(argument, [following_line]) arrangement = ArrangementWithSds( home_or_sds_contents=HomeOrSdsPopulatorForRelOptionType( parse_file_ref.ALL_REL_OPTIONS_CONFIG.options.default_option, fs.DirContents([file_to_interpret])), symbols=SymbolTable({ python_interpreter_symbol.name: su.string_constant_container(python_interpreter_symbol.value), file_to_interpret_symbol.name: su.string_constant_container(file_to_interpret_symbol.value), exit_code_symbol.name: su.string_constant_container(str(exit_code_symbol.value)), }), ) expectation = embryo_check.Expectation( source=assert_source(current_line_number=asrt.equals(2), column_index=asrt.equals(0)), symbol_usages=asrt.matches_sequence([ matches_reference_2( python_interpreter_symbol.name, equals_data_type_reference_restrictions( parse_file_ref.path_or_string_reference_restrictions( syntax_elements.REL_OPTION_ARG_CONF.options.accepted_relativity_variants ))), matches_reference_2( file_to_interpret_symbol.name, equals_data_type_reference_restrictions( parse_file_ref.path_or_string_reference_restrictions( parse_file_ref.ALL_REL_OPTIONS_CONFIG.options.accepted_relativity_variants ))), matches_reference_2( exit_code_symbol.name, equals_data_type_reference_restrictions(is_any_data_type() )), ]), main_result=spr_check.is_success_result(exit_code_symbol.value, ''), ) parser = sut.embryo_parser('instruction-name') embryo_check.check(self, parser, source, arrangement, expectation)
def test_set_value_SHOULD_be_able_to_have_symbol_references_in_the_right_hand_side(self): variable_name = 'variable_to_assign' my_symbol = NameAndValue('my_symbol', 'my symbol value') your_symbol = NameAndValue('your_symbol', 'your symbol value') value_template = 'pre {MY_SYMBOL} {YOUR_SYMBOL} post' expected_evaluated_value_string = value_template.format( MY_SYMBOL=my_symbol.value, YOUR_SYMBOL=your_symbol.value, ) expected_environ_after_main = { variable_name: expected_evaluated_value_string, } value_source_string = value_template.format( MY_SYMBOL=symbol_reference_syntax_for_name(my_symbol.name), YOUR_SYMBOL=symbol_reference_syntax_for_name(your_symbol.name), ) source_line = ' {variable_name} = {soft_quote}{source_value_string}{soft_quote}'.format( variable_name=variable_name, source_value_string=value_source_string, soft_quote=SOFT_QUOTE_CHAR, ) following_line = 'following line' source = remaining_source(source_line, [following_line]) arrangement = ArrangementWithSds( symbols=SymbolTable({ my_symbol.name: su.string_constant_container(my_symbol.value), your_symbol.name: su.string_constant_container(your_symbol.value), }), ) expectation = embryo_check.Expectation( main_side_effect_on_environment_variables=asrt.equals(expected_environ_after_main), symbol_usages=asrt.matches_sequence([ matches_reference_2( my_symbol.name, is_any_data_type_reference_restrictions()), matches_reference_2( your_symbol.name, is_any_data_type_reference_restrictions()), ]), source=assert_source(current_line_number=asrt.equals(2), column_index=asrt.equals(0)), ) parser = sut.EmbryoParser() embryo_check.check(self, parser, source, arrangement, expectation)
def source_cases(file_type: file_properties.FileType) -> list: return [ SourceCase('single name argument', remaining_source(type_matcher_of(file_type)), assert_source(is_at_eof=asrt.is_true), ), SourceCase('single name argument followed by space, and following lines', remaining_source(type_matcher_of(file_type) + space, ['following line']), assert_source(current_line_number=asrt.equals(1), remaining_part_of_current_line=asrt.equals(space[1:])), ), SourceCase('single name argument followed by arguments, and following lines', remaining_source(type_matcher_of(file_type) + space + name_glob_pattern_matcher_of('no-matching-file'), ['following line']), assert_source(current_line_number=asrt.equals(1), remaining_part_of_current_line=asrt.equals( space[1:] + name_glob_pattern_matcher_of('no-matching-file'))), ), ]
def test_symbol_references(self): file_to_interpret = fs.File( 'python-logic_symbol_utils.py', python_program_that_exits_with_code_given_as_first_cl_arg) file_to_interpret_symbol = StringConstantSymbolContext( 'file_to_interpret_symbol', file_to_interpret.file_name) python_interpreter_symbol = StringConstantSymbolContext( 'python_interpreter_symbol', sys.executable) exit_code_symbol = StringIntConstantSymbolContext( 'exit_code_symbol', 72) argument = ' {python_interpreter} {interpret_option} {file_to_interpret} "{exit_code}"'.format( python_interpreter=python_interpreter_symbol.name__sym_ref_syntax, interpret_option=args.option( syntax_elements.EXISTING_FILE_OPTION_NAME).as_str, file_to_interpret=file_to_interpret_symbol.name__sym_ref_syntax, exit_code=exit_code_symbol.name__sym_ref_syntax, ) following_line = 'following line' source = remaining_source(argument, [following_line]) arrangement = Arrangement.phase_agnostic( tcds=TcdsArrangement(tcds_contents=TcdsPopulatorForRelOptionType( path_relativities.ALL_REL_OPTIONS_ARG_CONFIG.options. default_option, fs.DirContents([file_to_interpret])), ), symbols=SymbolContext.symbol_table_of_contexts([ python_interpreter_symbol, file_to_interpret_symbol, exit_code_symbol, ]), ) expectation = Expectation.phase_agnostic( source=assert_source(current_line_number=asrt.equals(2), column_index=asrt.equals(0)), symbol_usages=asrt.matches_sequence([ python_interpreter_symbol.usage_assertion__path_or_string( syntax_elements.EXE_FILE_REL_OPTION_ARG_CONF.options. accepted_relativity_variants), file_to_interpret_symbol.usage_assertion__path_or_string( path_relativities.ALL_REL_OPTIONS_ARG_CONFIG.options. accepted_relativity_variants), exit_code_symbol.usage_assertion__w_str_rendering, ]), main_result=result_assertions.equals(exit_code_symbol.int_value, ''), ) parser = sut.embryo_parser('instruction-name') embryo_check.check(self, parser, source, arrangement, expectation)
def runTest(self): test_cases = [ ([''], 0, '', assert_source(is_at_eof=asrt.is_true, has_current_line=asrt.is_false) ), (['abc'], 0, 'abc', assert_source(is_at_eof=asrt.is_true, has_current_line=asrt.is_false) ), (['abc'], 1, 'bc', assert_source(is_at_eof=asrt.is_true, has_current_line=asrt.is_false) ), (['abc', 'def'], 0, 'abc', assert_source(is_at_eof=asrt.is_false, has_current_line=asrt.is_true, current_line_number=asrt.equals(2), remaining_part_of_current_line=asrt.equals('def')) ), (['abc', 'def'], 2, 'c', assert_source(is_at_eof=asrt.is_false, has_current_line=asrt.is_true, current_line_number=asrt.equals(2), remaining_part_of_current_line=asrt.equals('def')) ), ] for source_lines, num_chars_to_consume_before, expected_instr_arg, expected_source in test_cases: with self.subTest(): source = source_of_lines(source_lines) source.consume_part_of_current_line(num_chars_to_consume_before) instruction = self.parser.parse(ARBITRARY_FS_LOCATION_INFO, source) self.assertIsInstance(instruction, Instruction, 'Expects the Instruction to be returned') assert isinstance(instruction, Instruction) self.assertEqual(expected_instr_arg, instruction.argument, 'Instruction argument') expected_source.apply_with_message(self, source, 'source')
def test_symbol_references(self): python_interpreter_symbol = NameAndValue('python_interpreter_symbol', sys.executable) execute_program_option_symbol = NameAndValue('execute_program_option', '-c') exit_code_symbol = NameAndValue('exit_code_symbol', 87) argument = ' {python_interpreter} {execute_program_option} {source_option} exit({exit_code}) '.format( python_interpreter=symbol_reference_syntax_for_name(python_interpreter_symbol.name), execute_program_option=symbol_reference_syntax_for_name(execute_program_option_symbol.name), source_option=syntax_elements.REMAINING_PART_OF_CURRENT_LINE_AS_LITERAL_MARKER, exit_code=symbol_reference_syntax_for_name(str(exit_code_symbol.name)), ) arrangement = ArrangementWithSds( symbols=SymbolTable({ python_interpreter_symbol.name: su.string_constant_container(python_interpreter_symbol.value), execute_program_option_symbol.name: su.string_constant_container( execute_program_option_symbol.value), exit_code_symbol.name: su.string_constant_container(str(exit_code_symbol.value)), }), ) source = remaining_source(argument, ['following line']) expectation = embryo_check.Expectation( source=assert_source(current_line_number=asrt.equals(2), column_index=asrt.equals(0)), symbol_usages=asrt.matches_sequence([ matches_reference_2( python_interpreter_symbol.name, equals_data_type_reference_restrictions( parse_file_ref.path_or_string_reference_restrictions( syntax_elements.REL_OPTION_ARG_CONF.options.accepted_relativity_variants ))), matches_reference_2( execute_program_option_symbol.name, equals_data_type_reference_restrictions( is_any_data_type() )), matches_reference_2( exit_code_symbol.name, equals_data_type_reference_restrictions( is_any_data_type() )), ]), main_result=spr_check.is_success_result(exit_code_symbol.value, ''), ) parser = sut.embryo_parser('instruction-name') embryo_check.check(self, parser, source, arrangement, expectation)
def runTest(self): test_cases = [ ([''], 0, '', assert_source(is_at_eof=asrt.is_true, has_current_line=asrt.is_false)), (['abc'], 0, 'abc', assert_source(is_at_eof=asrt.is_true, has_current_line=asrt.is_false)), (['abc'], 1, 'bc', assert_source(is_at_eof=asrt.is_true, has_current_line=asrt.is_false)), (['abc', 'def'], 0, 'abc', assert_source(is_at_eof=asrt.is_false, has_current_line=asrt.is_true, current_line_number=asrt.equals(2), remaining_part_of_current_line=asrt.equals('def'))), (['abc', 'def'], 2, 'c', assert_source(is_at_eof=asrt.is_false, has_current_line=asrt.is_true, current_line_number=asrt.equals(2), remaining_part_of_current_line=asrt.equals('def'))), ] for source_lines, num_chars_to_consume_before, expected_instr_arg, expected_source in test_cases: with self.subTest(): source = source_of_lines(source_lines) source.consume_part_of_current_line( num_chars_to_consume_before) instruction = self.parser.parse(ARBITRARY_FS_LOCATION_INFO, source) self.assertIsInstance( instruction, Instruction, 'Expects the Instruction to be returned') assert isinstance(instruction, Instruction) self.assertEqual(expected_instr_arg, instruction.argument, 'Instruction argument') expected_source.apply_with_message(self, source, 'source')
def test_parse(self): pattern = 'include.*' space = ' ' cases = [ SourceCase('single name reg-ex argument', remaining_source(name_reg_ex_pattern_matcher_of(pattern)), assert_source(is_at_eof=asrt.is_true), ), SourceCase('single name reg-ex argument, including ignore-case option', remaining_source(name_reg_ex_pattern_matcher_of(pattern, ignore_case=True)), assert_source(is_at_eof=asrt.is_true), ), SourceCase('single name reg-ex argument followed by space, and following lines', remaining_source(name_reg_ex_pattern_matcher_of(pattern) + space, ['following line']), assert_source(current_line_number=asrt.equals(1), remaining_part_of_current_line=asrt.equals(space[1:])), ), SourceCase('single name reg-ex argument followed by arguments', remaining_source(name_reg_ex_pattern_matcher_of(pattern) + space + 'following argument', ['following line']), assert_source(current_line_number=asrt.equals(1), remaining_part_of_current_line=asrt.equals(space[1:] + 'following argument')), ), ] expected = file_matchers.FileMatcherBaseNameRegExPattern(re.compile(pattern)) for case in cases: with self.subTest(case=case.name): self._check_parse( case.source, Expectation( resolved_value_equals_file_matcher(expected), source=case.source_assertion, ) )
def test_successful_parse(self): # ARRANGE # symbol_ref = SymbolWithReferenceSyntax('validSymbol_name_1') single_symbol = [symbol(symbol_ref.name)] parse_source = ParseSource( _src('{soft_quote}{symbol_reference}{soft_quote} rest', soft_quote=SOFT_QUOTE_CHAR, symbol_reference=symbol_ref)) # ACT # actual = sut.parse_string_sdv_from_parse_source(parse_source) # ASSERT # assertion_on_result = assert_equals_string_sdv(single_symbol) assertion_on_result.apply_with_message(self, actual, 'result') assertion_on_parse_source = assert_source( remaining_part_of_current_line=asrt.equals('rest')) assertion_on_parse_source.apply_with_message(self, parse_source, 'parse_source')
def test_with_symbol_references(self): # ARRANGE # symbol_relativity = RelOptionType.REL_TMP default_relativity = RelOptionType.REL_RESULT accepted_path_relativity_variants = PathRelativityVariants({default_relativity, symbol_relativity}, absolute=False) rel_opt_arg_conf = RelOptionArgumentConfiguration( RelOptionsConfiguration(accepted_path_relativity_variants, default_relativity), 'ARG_SYNTAX_NAME', False ) symbol_path_suffix = 'symbol-path-suffix' symbol = NameAndValue('path_symbol', file_refs.of_rel_option( symbol_relativity, concrete_path_parts.fixed_path_parts(symbol_path_suffix))) file_name = 'file' source = remaining_source_lines( ['{file_option} {rel_symbol_option} {file_name} following args'.format( rel_symbol_option=relativity_arguments.rel_symbol_arg_str(symbol.name), file_option=option_syntax(sut.FILE_ARGUMENT_OPTION), file_name=file_name, ), 'following line', ]) # EXPECTATION # expectation = ExpectedFileRef( file_ref_value=file_refs.of_rel_option(symbol_relativity, concrete_path_parts.fixed_path_parts([symbol_path_suffix, file_name])), common=CommonExpectation( symbol_references=[SymbolReference(symbol.name, file_ref_reference_restrictions( accepted_path_relativity_variants))], source=asrt_source.assert_source(current_line_number=asrt.equals(1), remaining_part_of_current_line=asrt.equals( 'following args')), symbol_table=singleton_symbol_table_2(symbol.name, file_ref_constant_container(symbol.value))) ) # ACT & ASSERT # _expect_file_ref(self, source, expectation, rel_opt_arg_conf)
def test_valid_token(self): test_cases = [ ('token', assert_plain('token'), assert_source(is_at_eol=asrt.is_true, has_current_line=asrt.is_true, current_line_number=asrt.equals(1))), ('<<->> other_token', assert_plain('<<->>'), source_is_not_at_end( remaining_part_of_current_line=asrt.equals(' other_token'), current_line_number=asrt.equals(1))), ] for first_line, token_assertion, source_assertion in test_cases: with self.subTest(msg=repr(first_line)): source = remaining_source(first_line) actual = sut.parse_token_or_none_on_current_line(source) token_assertion.apply_with_message(self, actual, 'token') source_assertion.apply_with_message(self, source, 'source')
def test_valid_token(self): test_cases = [ ('token', assert_plain('token'), assert_source(is_at_eol=asrt.is_true, has_current_line=asrt.is_true, current_line_number=asrt.equals(1))), ('<<->> other_token', assert_plain('<<->>'), source_is_not_at_end(remaining_part_of_current_line=asrt.equals(' other_token'), current_line_number=asrt.equals(1))), ] for first_line, token_assertion, source_assertion in test_cases: with self.subTest(msg=repr(first_line)): source = remaining_source(first_line) actual = sut.parse_token_or_none_on_current_line(source) token_assertion.apply_with_message(self, actual, 'token') source_assertion.apply_with_message(self, source, 'source')
def test_symbol_references(self): python_interpreter_symbol = StringConstantSymbolContext( 'python_interpreter_symbol', sys.executable) execute_program_option_symbol = StringConstantSymbolContext( 'execute_program_option', '-c') exit_code_symbol = StringIntConstantSymbolContext( 'exit_code_symbol', 87) argument = ' {python_interpreter} {execute_program_option} {source_option} exit({exit_code}) '.format( python_interpreter=python_interpreter_symbol.name__sym_ref_syntax, execute_program_option=execute_program_option_symbol. name__sym_ref_syntax, source_option=syntax_elements. REMAINING_PART_OF_CURRENT_LINE_AS_LITERAL_MARKER, exit_code=exit_code_symbol.name__sym_ref_syntax, ) arrangement = Arrangement.phase_agnostic( symbols=SymbolContext.symbol_table_of_contexts([ python_interpreter_symbol, execute_program_option_symbol, exit_code_symbol, ]), tcds=TcdsArrangement(), ) source = remaining_source(argument, ['following line']) expectation = Expectation.phase_agnostic( source=assert_source(current_line_number=asrt.equals(2), column_index=asrt.equals(0)), symbol_usages=asrt.matches_sequence([ python_interpreter_symbol.usage_assertion__path_or_string( syntax_elements.EXE_FILE_REL_OPTION_ARG_CONF.options. accepted_relativity_variants), execute_program_option_symbol.usage_assertion__w_str_rendering, exit_code_symbol.usage_assertion__w_str_rendering, ]), main_result=result_assertions.equals(exit_code_symbol.int_value, ''), ) parser = sut.embryo_parser('instruction-name') embryo_check.check(self, parser, source, arrangement, expectation)
def test_without_symbol_references(self): file_name = 'file' source = remaining_source_lines( ['{file_option} {file_name} following args'.format( file_option=option_syntax(sut.FILE_ARGUMENT_OPTION), file_name=file_name, ), 'following line', ]) expectation = ExpectedFileRef( file_ref_value=file_refs.of_rel_option(sut.CONFIGURATION.options.default_option, concrete_path_parts.fixed_path_parts(file_name)), common=CommonExpectation( symbol_references=[], source=asrt_source.assert_source(current_line_number=asrt.equals(1), remaining_part_of_current_line=asrt.equals( 'following args'))) ) _expect_file_ref(self, source, expectation)
def test_symbol_references(self): expected_exit_status = 72 file_to_interpret = fs.File('python-logic_symbol_utils.py', py_script_that_exists_with_status(expected_exit_status)) file_to_interpret_symbol = StringConstantSymbolContext('file_to_interpret_symbol', file_to_interpret.file_name) python_interpreter_symbol = StringConstantSymbolContext('python_interpreter_symbol', sys.executable) argument = ' "{python_interpreter}" {file_to_interpret}'.format( python_interpreter=python_interpreter_symbol.name__sym_ref_syntax, file_to_interpret=file_to_interpret_symbol.name__sym_ref_syntax, ) following_line = 'following line' source = remaining_source(argument, [following_line]) arrangement = Arrangement.phase_agnostic( tcds=TcdsArrangement( tcds_contents=TcdsPopulatorForRelOptionType( RelOptionType.REL_ACT, fs.DirContents([file_to_interpret])), ), symbols=SymbolContext.symbol_table_of_contexts([ python_interpreter_symbol, file_to_interpret_symbol, ]), ) expectation = Expectation.phase_agnostic( source=assert_source(current_line_number=asrt.equals(2), column_index=asrt.equals(0)), symbol_usages=asrt.matches_sequence([ python_interpreter_symbol.usage_assertion__w_str_rendering, file_to_interpret_symbol.usage_assertion__w_str_rendering, ]), main_result=result_assertions.equals(expected_exit_status, ''), ) parser = sut.embryo_parser('instruction-name') embryo_check.check(self, parser, source, arrangement, expectation)
def test_consume_initial_space(self): test_cases = [ (['', 'second line'], '', True), (['non-space', 'second line'], 'non-space', False), ([' ', 'second line'], '', True), ([' non-space', 'second line'], 'non-space', False), ] for lines, remaining_part, is_at_eol in test_cases: with self.subTest(): first_line = lines[0] source_lines = '\n'.join(lines) # ACT # source = ParseSource(source_lines) # ASSERT # source.consume_initial_space_on_current_line() assertion = assert_source(is_at_eol=asrt.equals(is_at_eol), remaining_part_of_current_line=asrt.equals(remaining_part), current_line_number=asrt.equals(1), current_line_text=asrt.equals(lines[0]), column_index=asrt.equals(len(first_line) - len(first_line.lstrip())) ) assertion.apply(self, source)
def test_set_value_with_hard_quoted_value_SHOULD_skip_symbol_substitution(self): variable_name = 'variable_to_assign' my_symbol = NameAndValue('my_symbol', 'my symbol value') your_symbol = NameAndValue('your_symbol', 'your symbol value') value_template = 'pre {MY_SYMBOL} {YOUR_SYMBOL} post' value_source_string = value_template.format( MY_SYMBOL=symbol_reference_syntax_for_name(my_symbol.name), YOUR_SYMBOL=symbol_reference_syntax_for_name(your_symbol.name), ) expected_environ_after_main = { variable_name: value_source_string, } source_line = ' {variable_name} = {hard_quote}{source_value_string}{hard_quote}'.format( variable_name=variable_name, source_value_string=value_source_string, hard_quote=HARD_QUOTE_CHAR, ) following_line = 'following line' source = remaining_source(source_line, [following_line]) arrangement = ArrangementWithSds() expectation = embryo_check.Expectation( main_side_effect_on_environment_variables=asrt.equals(expected_environ_after_main), symbol_usages=asrt.matches_sequence([]), source=assert_source(current_line_number=asrt.equals(2), column_index=asrt.equals(0)), ) parser = sut.EmbryoParser() embryo_check.check(self, parser, source, arrangement, expectation)
def test_successful_parse(self): # ARRANGE # cases = [ Case(comparators.EQ.name + ' plain integer', remaining_source(comparators.EQ.name + ' 1'), source_assertion= assert_source(is_at_eol=asrt.is_true), result_assertion=is_equivalent_to(matcher_of(comparators.EQ, 1), [ model_of(-1), model_of(1), model_of(2), ])), Case(comparators.NE.name, remaining_source(comparators.NE.name + ' 1'), source_assertion= assert_source(is_at_eol=asrt.is_true), result_assertion=is_equivalent_to(matcher_of(comparators.NE, 1), [ model_of(-1), model_of(1), model_of(2), ])), Case(comparators.LT.name, remaining_source(comparators.LT.name + ' 69'), source_assertion= assert_source(is_at_eol=asrt.is_true), result_assertion=is_equivalent_to(matcher_of(comparators.LT, 69), [ model_of(60), model_of(69), model_of(72), ])), Case(comparators.LTE.name, remaining_source(comparators.LTE.name + ' 69'), source_assertion= assert_source(is_at_eol=asrt.is_true), result_assertion=is_equivalent_to(matcher_of(comparators.LTE, 69), [ model_of(60), model_of(69), model_of(72), ])), Case(comparators.GT.name, remaining_source(comparators.GT.name + ' 69'), source_assertion= assert_source(is_at_eol=asrt.is_true), result_assertion=is_equivalent_to(matcher_of(comparators.GT, 69), [ model_of(60), model_of(69), model_of(72), ])), Case(comparators.GTE.name, remaining_source(comparators.GTE.name + ' 69'), source_assertion= assert_source(is_at_eol=asrt.is_true), result_assertion=is_equivalent_to(matcher_of(comparators.GTE, 69), [ model_of(60), model_of(69), model_of(72), ])), Case(comparators.GTE.name + ' following content on line', remaining_source(comparators.GTE.name + ' 72 next'), source_assertion= assert_source(remaining_part_of_current_line=asrt.equals('next')), result_assertion=is_equivalent_to(matcher_of(comparators.GTE, 72), [ model_of(69), model_of(72), model_of(80), ])), Case(comparators.EQ.name + ' integer expression', remaining_source('== "69+72"'), source_assertion= assert_source(is_at_eol=asrt.is_true), result_assertion=is_equivalent_to(matcher_of(comparators.EQ, 69 + 72), [ model_of(69 + 72 - 1), model_of(69 + 72), model_of(69 + 72 + 1), ])), ] for case in cases: with from_parse_source(case.source) as parser: # ACT # actual = sut.parse_integer_matcher(parser, _NAME_OF_LHS) # ASSERT # case.source_assertion.apply_with_message(self, case.source, 'source') case.result_assertion.apply_with_message(self, actual, 'parsed value')
def test(self): single_token_value = 'single_token_value' string_symbol = NameAndValue('string_symbol_name', 'string symbol value') cases = [ Case( 'single string constant, at end of line, on the last line', source=remaining_source(single_token_value), expectation=Expectation( elements=[list_sdvs.str_element(single_token_value)], source=assert_source(is_at_eof=asrt.is_true)), ), Case( 'single symbol reference, at end of line, on the last line', source=remaining_source( symbol_reference_syntax_for_name(string_symbol.name)), expectation=Expectation( elements=[ list_sdvs.symbol_element( reference_to__on_direct_and_indirect( string_symbol.name)) ], source=assert_source(is_at_eof=asrt.is_true), references=asrt.matches_sequence([ asrt_sym_ref.matches_reference_2( string_symbol.name, asrt_data_rest.is__w_str_rendering()) ])), ), Case( 'complex element (str const and sym-refs), at end of line, on the last line', source=remaining_source( single_token_value + symbol_reference_syntax_for_name(string_symbol.name)), expectation=Expectation( elements=[ list_sdvs.string_element( string_sdvs.from_fragments( [ string_sdvs.str_fragment( single_token_value), string_sdvs.symbol_fragment( SymbolReference( string_symbol.name, reference_restrictions. is_any_type_w_str_rendering(), )), ])) ], references=asrt.matches_sequence([ asrt_sym_ref.matches_reference_2( string_symbol.name, asrt_data_rest.is__w_str_rendering()) ]), source=asrt_source.is_at_end_of_line(1)), ), Case( 'single element, followed by more than one space, on the last line', source=remaining_source(single_token_value + ' ', []), expectation=Expectation( elements=[list_sdvs.str_element(single_token_value)], source=asrt_source.is_at_end_of_line(1)), ), Case( 'single element, followed by single space, on the last line', source=remaining_source(single_token_value + ' ', []), expectation=Expectation( elements=[list_sdvs.str_element(single_token_value)], source=asrt_source.is_at_end_of_line(1)), ), Case( 'single element, followed by space, followed by empty line', source=remaining_source(single_token_value + ' ', ['']), expectation=Expectation( elements=[list_sdvs.str_element(single_token_value)], source=asrt_source.is_at_end_of_line(1)), ), Case( 'single element, at end of line, followed by line with only space', source=remaining_source(single_token_value, [' ']), expectation=Expectation( elements=[list_sdvs.str_element(single_token_value)], source=asrt_source.is_at_end_of_line(1)), ), Case( 'single element, followed by space, followed by line with only space', source=remaining_source(single_token_value + ' ', [' ']), expectation=Expectation( elements=[list_sdvs.str_element(single_token_value)], source=asrt_source.is_at_end_of_line(1)), ), Case( 'single element, at end of line, followed by line with invalid quoting', source=remaining_source(single_token_value, ['" ']), expectation=Expectation( elements=[list_sdvs.str_element(single_token_value)], source=asrt_source.is_at_end_of_line(1)), ), Case( 'continuation token, followed by line with single element', source=remaining_source(defs.CONTINUATION_TOKEN, [single_token_value]), expectation=Expectation( elements=[list_sdvs.str_element(single_token_value)], source=asrt_source.is_at_end_of_line(2)), ), Case( 'single element, followed by continuation token, followed by empty line', source=remaining_source( single_token_value + ' ' + defs.CONTINUATION_TOKEN, ['']), expectation=Expectation( elements=[list_sdvs.str_element(single_token_value)], source=asrt_source.is_at_end_of_line(2)), ), Case( 'single element, followed by r-paren and more', source=remaining_source( ' '.join((single_token_value, reserved_words.PAREN_END, 'const_str')), ['" ']), expectation=Expectation( elements=[list_sdvs.str_element(single_token_value)], source=asrt_source.source_is_not_at_end( current_line_number=asrt.equals(1), remaining_part_of_current_line=asrt.equals(' '.join( (reserved_words.PAREN_END, 'const_str'))))), ), ] # ACT & ASSERT # _test_cases(self, cases)
def test(self): single_token_value = 'single_token_value' string_symbol = NameAndValue('string_symbol_name', 'string symbol value') cases = [ Case('single string constant, at end of line, on the last line', source= remaining_source(single_token_value), expectation= Expectation(elements= [list_resolvers.str_element(single_token_value)], source= assert_source(is_at_eof=asrt.is_true)), ), Case('single symbol reference, at end of line, on the last line', source= remaining_source(symbol_reference_syntax_for_name(string_symbol.name)), expectation= Expectation(elements= [list_resolvers.symbol_element(symbol_reference(string_symbol.name))], source= assert_source(is_at_eof=asrt.is_true), references= asrt.matches_sequence([asrt_sym_ref.matches_reference_2( string_symbol.name, is_any_data_type_reference_restrictions()) ])), ), Case('complex element (str const and sym-refs), at end of line, on the last line', source= remaining_source(single_token_value + symbol_reference_syntax_for_name(string_symbol.name)), expectation= Expectation( elements= [ list_resolvers.string_element(string_resolvers.from_fragments([ string_resolvers.str_fragment(single_token_value), string_resolvers.symbol_fragment( SymbolReference(string_symbol.name, reference_restrictions.is_any_data_type()) ), ]))], references= asrt.matches_sequence([asrt_sym_ref.matches_reference_2( string_symbol.name, is_any_data_type_reference_restrictions()) ]), source= asrt_source.is_at_end_of_line(1)), ), Case('single element, followed by more than one space, on the last line', source= remaining_source(single_token_value + ' ', []), expectation= Expectation(elements= [list_resolvers.str_element(single_token_value)], source= asrt_source.is_at_line(1, ' ')), ), Case('single element, followed by single space, on the last line', source= remaining_source(single_token_value + ' ', []), expectation= Expectation(elements= [list_resolvers.str_element(single_token_value)], source= asrt_source.is_at_end_of_line(1)), ), Case('single element, followed by space, followed by empty line', source= remaining_source(single_token_value + ' ', ['']), expectation= Expectation(elements= [list_resolvers.str_element(single_token_value)], source= asrt_source.is_at_line(1, ' ')), ), Case('single element, at end of line, followed by line with only space', source= remaining_source(single_token_value, [' ']), expectation= Expectation(elements= [list_resolvers.str_element(single_token_value)], source= asrt_source.is_at_end_of_line(1)), ), Case('single element, followed by space, followed by line with only space', source= remaining_source(single_token_value + ' ', [' ']), expectation= Expectation(elements= [list_resolvers.str_element(single_token_value)], source= asrt_source.is_at_line(1, ' ')), ), Case('single element, at end of line, followed by line with invalid quoting', source= remaining_source(single_token_value, ['" ']), expectation= Expectation(elements= [list_resolvers.str_element(single_token_value)], source= asrt_source.is_at_end_of_line(1)), ), ] # ACT & ASSERT # _test_cases(self, cases)
def test_valid_syntax_without_symbol_references(self): single_string_token_value = 'singleStringTokenValue' multiple_tokens_string_value = 'multiple tokens string value' following_arg_token = 'singleToken' cases = [ NameAndValue('non-quoted string-token on single line', ( [ single_string_token_value, ], ExpectedString(single_string_token_value, CommonExpectation( symbol_references=[], source=asrt_source.is_at_end_of_line(1))) ) ), NameAndValue('non-quoted string-token on following line', ( [ '', single_string_token_value, ], ExpectedString(single_string_token_value, CommonExpectation( symbol_references=[], source=asrt_source.is_at_end_of_line(2))) ) ), NameAndValue('non-quoted string-token on single line, followed by arguments on same line', ( [ '{string_token} {following_argument}'.format( string_token=single_string_token_value, following_argument=following_arg_token, ) ], ExpectedString(single_string_token_value, CommonExpectation( symbol_references=[], source=asrt_source.assert_source( current_line_number=asrt.equals(1), remaining_part_of_current_line=asrt.equals( following_arg_token)))) ) ), NameAndValue('quoted string-token on single line', ( [ surrounded_by_soft_quotes_str(multiple_tokens_string_value), ], ExpectedString(multiple_tokens_string_value, CommonExpectation( symbol_references=[], source=asrt_source.is_at_end_of_line(1))) ) ), ] for case in cases: source_lines, expected_string = case.value source = remaining_source_lines(source_lines) with self.subTest(case_name=case.name): _expect_string(self, source, expected_string)
def test_consume_with_valid_arguments(self): test_cases = [ (TestSetupForConsume('one whole line and part of next, with one line remaining', source_lines=['123', '45', '6'], number_of_characters_to_consume_from_current_line_before_test=0, number_of_characters_to_consume=4 + 1), assert_source(is_at_eof=asrt.equals(False), is_at_eol=asrt.equals(False), is_at_eol__except_for_space=asrt.equals(False), has_current_line=asrt.equals(True), current_line_number=asrt.equals(2), current_line_text=asrt.equals('45'), column_index=asrt.equals(1), remaining_part_of_current_line=asrt.equals('5'), remaining_source=asrt.equals('5\n6'))), (TestSetupForConsume('one whole line and part of next, with one line remaining, on column index 1', source_lines=['123', '45', '6'], number_of_characters_to_consume_from_current_line_before_test=1, number_of_characters_to_consume=4 + 1 - 1), assert_source(is_at_eof=asrt.equals(False), is_at_eol=asrt.equals(False), is_at_eol__except_for_space=asrt.equals(False), has_current_line=asrt.equals(True), current_line_number=asrt.equals(2), current_line_text=asrt.equals('45'), column_index=asrt.equals(1), remaining_part_of_current_line=asrt.equals('5'), remaining_source=asrt.equals('5\n6'))), (TestSetupForConsume('two whole lines, with one line remaining', source_lines=['123', '45', '6'], number_of_characters_to_consume_from_current_line_before_test=0, number_of_characters_to_consume=5 + 1), assert_source(is_at_eof=asrt.equals(False), is_at_eol=asrt.equals(True), is_at_eol__except_for_space=asrt.equals(True), has_current_line=asrt.equals(True), current_line_number=asrt.equals(2), current_line_text=asrt.equals('45'), column_index=asrt.equals(2), remaining_part_of_current_line=asrt.equals(''), remaining_source=asrt.equals('\n6'))), (TestSetupForConsume('two whole lines, with one line remaining, on column index 2', source_lines=['123', '45', '6'], number_of_characters_to_consume_from_current_line_before_test=2, number_of_characters_to_consume=5 + 1 - 2), assert_source(is_at_eof=asrt.equals(False), is_at_eol=asrt.equals(True), is_at_eol__except_for_space=asrt.equals(True), has_current_line=asrt.equals(True), current_line_number=asrt.equals(2), current_line_text=asrt.equals('45'), column_index=asrt.equals(2), remaining_part_of_current_line=asrt.equals(''), remaining_source=asrt.equals('\n6'))), (TestSetupForConsume('two whole lines, with no line after', source_lines=['123', '45'], number_of_characters_to_consume_from_current_line_before_test=0, number_of_characters_to_consume=5 + 1), assert_source(is_at_eof=asrt.equals(True), is_at_eol=asrt.equals(True), is_at_eol__except_for_space=asrt.equals(True), has_current_line=asrt.equals(True), current_line_number=asrt.equals(2), current_line_text=asrt.equals('45'), remaining_part_of_current_line=asrt.equals(''), remaining_source=asrt.equals(''))), (TestSetupForConsume('two whole lines, with no line after, on column index 3', source_lines=['123', '45'], number_of_characters_to_consume_from_current_line_before_test=3, number_of_characters_to_consume=5 + 1 - 3), assert_source(is_at_eof=asrt.equals(True), is_at_eol=asrt.equals(True), is_at_eol__except_for_space=asrt.equals(True), has_current_line=asrt.equals(True), current_line_number=asrt.equals(2), current_line_text=asrt.equals('45'), column_index=asrt.equals(2), remaining_part_of_current_line=asrt.equals(''), remaining_source=asrt.equals(''))), ] for setup, assertion in test_cases: with self.subTest(case_name=setup.name): source_lines = '\n'.join(setup.source_lines) source = ParseSource(source_lines) source.consume_part_of_current_line(setup.number_of_characters_to_consume_from_current_line_before_test) source.consume(setup.number_of_characters_to_consume) assertion.apply(self, source, asrt.MessageBuilder(setup.name))
def test_valid_syntax_with_symbol_references(self): symbol = NameAndValue('symbol_name', 'symbol value') before_symbol = 'text before symbol' after_symbol = 'text after symbol' following_arg_token = 'singleToken' cases = [ NameAndValue('single unquoted symbol reference', ( [ symbol_reference_syntax_for_name(symbol.name), ], ExpectedString(symbol.value, CommonExpectation( symbol_references=[ references.reference_to_any_data_type_value(symbol.name), ], source=asrt_source.is_at_end_of_line(1), symbol_table=singleton_symbol_table_2(symbol.name, string_constant_container( symbol.value)), ) ) ) ), NameAndValue('single unquoted symbol reference followed by args on same line', ( [ '{sym_ref} {following_argument}'.format( sym_ref=symbol_reference_syntax_for_name(symbol.name), following_argument=following_arg_token, ), ], ExpectedString(symbol.value, CommonExpectation( symbol_references=[ references.reference_to_any_data_type_value(symbol.name), ], source=asrt_source.assert_source( current_line_number=asrt.equals(1), remaining_part_of_current_line=asrt.equals( following_arg_token)), symbol_table=singleton_symbol_table_2(symbol.name, string_constant_container( symbol.value)), ), ) ) ), NameAndValue('reference embedded in quoted string', ( [ '{soft_quote}{before_sym_ref}{sym_ref}{after_sym_ref}{soft_quote}'.format( soft_quote=SOFT_QUOTE_CHAR, sym_ref=symbol_reference_syntax_for_name(symbol.name), before_sym_ref=before_symbol, after_sym_ref=after_symbol, ) ], ExpectedString(before_symbol + symbol.value + after_symbol, CommonExpectation( symbol_references=[ references.reference_to_any_data_type_value(symbol.name), ], source=asrt_source.is_at_end_of_line(1), symbol_table=singleton_symbol_table_2(symbol.name, string_constant_container( symbol.value)), ) ) ) ), ] for case in cases: source_lines, expected_string = case.value source = remaining_source_lines(source_lines) with self.subTest(case_name=case.name): _expect_string(self, source, expected_string)
class TestParseSource(unittest.TestCase): test_cases_for_consume_all_characters_of_current_line = [ ('single line', assert_source(is_at_eof=asrt.is_true, has_current_line=asrt.is_true, column_index=asrt.equals(len('single line')), is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, remaining_source=asrt.equals('')) ), ('', assert_source(is_at_eof=asrt.is_true, has_current_line=asrt.is_true, column_index=asrt.equals(0), is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, remaining_source=asrt.equals('')) ), ('first line\nsecond line', assert_source(is_at_eof=asrt.is_false, has_current_line=asrt.is_true, is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, current_line_number=asrt.equals(1), current_line_text=asrt.equals('first line'), column_index=asrt.equals(len('first line')), remaining_source=asrt.equals('\nsecond line')) ), ('single line\n', assert_source(is_at_eof=asrt.is_false, has_current_line=asrt.is_true, is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, current_line_number=asrt.equals(1), current_line_text=asrt.equals('single line'), column_index=asrt.equals(len('single line')), remaining_source=asrt.equals('\n')) ), ('\n', assert_source(is_at_eof=asrt.is_false, has_current_line=asrt.is_true, is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, current_line_number=asrt.equals(1), current_line_text=asrt.equals(''), column_index=asrt.equals(0), remaining_source=asrt.equals('\n')) ), ('\nsecond line', assert_source(is_at_eof=asrt.is_false, has_current_line=asrt.is_true, is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, current_line_number=asrt.equals(1), current_line_text=asrt.equals(''), column_index=asrt.equals(0), remaining_source=asrt.equals('\nsecond line')) ), ] def _assert_current_line_and_remaining_part_of_it_is(self, line_number: int, line_text: str, source: ParseSource): self._assert_current_line_is(line_number, line_text, source) self.assertEqual(line_text, source.remaining_part_of_current_line, 'Remaining part of current line') def _assert_current_line_is(self, line_number: int, line_text: str, source: ParseSource): self.assertEqual(line_text, source.current_line_text, 'Text of current line') self.assertEqual(line_number, source.current_line_number, 'Line number of current line') self.assertEqual(line_text, source.current_line.text, 'Text of current line (extracted via Line)') self.assertEqual(line_number, source.current_line.line_number, 'Line number of current line (extracted via Line)') def _assert_is_at_eof(self, source: ParseSource): self.assertTrue(source.is_at_eof) self.assertEqual('', source.remaining_source, 'remaining source') def _assert_is_at_eol(self, source: ParseSource): self.assertTrue(source.is_at_eol) self.assertEqual('', source.remaining_part_of_current_line, 'remaining_part_of_current_line') def test_construction(self): test_cases = [ ('single line', assert_source(is_at_eof=asrt.is_false, is_at_eol=asrt.is_false, is_at_eol__except_for_space=asrt.is_false, has_current_line=asrt.is_true, column_index=asrt.equals(0), current_line_number=asrt.equals(1), current_line_text=asrt.equals('single line')) ), ('', assert_source(is_at_eof=asrt.is_true, is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, has_current_line=asrt.is_true, column_index=asrt.equals(0), current_line_number=asrt.equals(1), current_line_text=asrt.equals('')) ), ('first line\nsecond line', assert_source(is_at_eof=asrt.is_false, is_at_eol=asrt.is_false, is_at_eol__except_for_space=asrt.is_false, has_current_line=asrt.is_true, column_index=asrt.equals(0), current_line_number=asrt.equals(1), current_line_text=asrt.equals('first line')) ), ('single line\n', assert_source(is_at_eof=asrt.is_false, is_at_eol=asrt.is_false, is_at_eol__except_for_space=asrt.is_false, has_current_line=asrt.is_true, column_index=asrt.equals(0), current_line_number=asrt.equals(1), current_line_text=asrt.equals('single line')) ), ('\n', assert_source(is_at_eof=asrt.is_false, is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, has_current_line=asrt.is_true, column_index=asrt.equals(0), current_line_number=asrt.equals(1), current_line_text=asrt.equals('')) ), ('\nsecond line', assert_source(is_at_eof=asrt.is_false, is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, has_current_line=asrt.is_true, column_index=asrt.equals(0), current_line_number=asrt.equals(1), current_line_text=asrt.equals('')) ), ] for source_string, expectation in test_cases: with self.subTest(msg='construction:' + repr(source_string)): source = ParseSource(source_string) expectation.apply_with_message(self, source, 'construction:{}'.format(repr(source_string))) def test_only_newline2(self): source = ParseSource('\n\n') source.consume_current_line() self.assertFalse(source.is_at_eof) self.assertTrue(source.has_current_line, 'has_current_line') self._assert_is_at_eol(source) self._assert_current_line_is(2, '', source) def test_consume_current_line(self): test_cases = [ ('single line', assert_source(is_at_eof=asrt.is_true, has_current_line=asrt.is_false, remaining_source=asrt.equals('')) ), ('', assert_source(is_at_eof=asrt.is_true, has_current_line=asrt.is_false) ), ('first line\nsecond line', assert_source(is_at_eof=asrt.is_false, has_current_line=asrt.is_true, is_at_eol=asrt.is_false, is_at_eol__except_for_space=asrt.is_false, current_line_number=asrt.equals(2), current_line_text=asrt.equals('second line'), column_index=asrt.equals(0), remaining_source=asrt.equals('second line')) ), ('single line\n', assert_source(is_at_eof=asrt.is_true, has_current_line=asrt.is_true, is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, current_line_number=asrt.equals(2), current_line_text=asrt.equals(''), column_index=asrt.equals(0), remaining_source=asrt.equals('')) ), ('\n', assert_source(is_at_eof=asrt.is_true, has_current_line=asrt.is_true, is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, current_line_number=asrt.equals(2), current_line_text=asrt.equals(''), column_index=asrt.equals(0), remaining_source=asrt.equals('')) ), ('\nsecond line', assert_source(is_at_eof=asrt.is_false, has_current_line=asrt.is_true, is_at_eol=asrt.is_false, is_at_eol__except_for_space=asrt.is_false, current_line_number=asrt.equals(2), current_line_text=asrt.equals('second line'), column_index=asrt.equals(0), remaining_source=asrt.equals('second line')) ), ] for source_string, expectation in test_cases: with self.subTest(msg='consume current line: ' + repr(source_string)): source = ParseSource(source_string) source.consume_current_line() expectation.apply_with_message(self, source, 'consume_current_line:{}'.format(repr(source_string))) def test_consume_part_of_current_line__consume_all_characters(self): for source_string, expectation in self.test_cases_for_consume_all_characters_of_current_line: with self.subTest(msg='consume_part_of_current_line: ' + repr(source_string)): source = ParseSource(source_string) source.consume_part_of_current_line(len(source.current_line_text)) expectation.apply_with_message(self, source, 'consume_part_of_current_line:{}'.format(repr(source_string))) def test_consume__consume_all_characters_of_current_line(self): for source_string, expectation in self.test_cases_for_consume_all_characters_of_current_line: with self.subTest(msg='consume: ' + repr(source_string)): source = ParseSource(source_string) source.consume(len(source.current_line_text)) expectation.apply_with_message(self, source, 'consume:{}'.format(repr(source_string))) def test_consume__consume_all_characters_of_current_line_plus_one(self): test_cases = [ ('first line\nsecond line', assert_source(is_at_eof=asrt.is_false, has_current_line=asrt.is_true, is_at_eol=asrt.is_false, is_at_eol__except_for_space=asrt.is_false, current_line_number=asrt.equals(2), current_line_text=asrt.equals('second line'), column_index=asrt.equals(0), remaining_source=asrt.equals('second line')) ), ('single line\n', assert_source(is_at_eof=asrt.is_true, has_current_line=asrt.is_true, is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, current_line_number=asrt.equals(2), current_line_text=asrt.equals(''), column_index=asrt.equals(0), remaining_source=asrt.equals('')) ), ('\n', assert_source(is_at_eof=asrt.is_true, has_current_line=asrt.is_true, is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, current_line_number=asrt.equals(2), current_line_text=asrt.equals(''), column_index=asrt.equals(0), remaining_source=asrt.equals('')) ), ('\nsecond line', assert_source(is_at_eof=asrt.is_false, has_current_line=asrt.is_true, is_at_eol=asrt.is_false, is_at_eol__except_for_space=asrt.is_false, current_line_number=asrt.equals(2), current_line_text=asrt.equals('second line'), column_index=asrt.equals(0), remaining_source=asrt.equals('second line')) ), ] for source_string, expectation in test_cases: with self.subTest(msg='consume len(current line)+1: ' + repr(source_string)): source = ParseSource(source_string) source.consume(1 + len(source.current_line_text)) expectation.apply_with_message(self, source, 'consume len(current line)+1:{}'.format(repr(source_string))) def test_single_line_source(self): source = ParseSource('single line') self._assert_current_line_and_remaining_part_of_it_is(1, 'single line', source) self.assertEqual('single line', source.remaining_source, 'remaining source') source.consume_current_line() self._assert_is_at_eof(source) def test_two_line_source(self): original_source = 'first line' + '\n' + 'second line' source = ParseSource(original_source) self._assert_current_line_and_remaining_part_of_it_is(1, 'first line', source) self.assertEqual(original_source, source.remaining_source, 'remaining source') source.consume_current_line() self._assert_current_line_and_remaining_part_of_it_is(2, 'second line', source) self.assertEqual('second line', source.remaining_source, 'remaining source') source.consume_current_line() self._assert_is_at_eof(source) def test_first_line_is_empty(self): source = ParseSource('\n' + 'second line') self._assert_current_line_and_remaining_part_of_it_is(1, '', source) source.consume_current_line() self._assert_current_line_and_remaining_part_of_it_is(2, 'second line', source) self.assertEqual('second line', source.remaining_source, 'remaining source') source.consume_current_line() self._assert_is_at_eof(source) def test_last_line_is_empty(self): source = ParseSource('first line' + '\n') self._assert_current_line_and_remaining_part_of_it_is(1, 'first line', source) source.consume_current_line() self._assert_current_line_and_remaining_part_of_it_is(2, '', source) source.consume_current_line() self._assert_is_at_eof(source) def test_consume_part_of_current_line(self): source = ParseSource('first line' + '\n' + 'second line') source.consume_part_of_current_line(len('first') + 1) self._assert_current_line_is(1, 'first line', source) self.assertEqual('line', source.remaining_part_of_current_line, 'Remaining part of current line') self.assertEqual('line' + '\n' + 'second line', source.remaining_source, 'Remaining source') self.assertFalse(source.is_at_eof, 'is_at_eof') self.assertFalse(source.is_at_eol, 'is_at_eol') def test_consume_part_of_current_line__until_end_of_line_of_last_line(self): source = ParseSource('first line') source.consume_part_of_current_line(len('first line')) self._assert_current_line_is(1, 'first line', source) self.assertTrue(source.is_at_eol, 'is_at_eol') self.assertTrue(source.is_at_eof, 'is_at_eof') self.assertEqual('', source.remaining_part_of_current_line, 'Remaining part of current line') self.assertEqual('', source.remaining_source, 'Remaining source') def test_raise_exception_when_too_many_characters_are_consumed(self): source = ParseSource('first line' + '\n' + 'second line') with self.assertRaises(ValueError): source.consume_part_of_current_line(len('first line') + 1) self.assertEqual('first line', source.remaining_part_of_current_line, 'remaining_part_of_current_line should not have been updated') def test_consume_initial_space(self): test_cases = [ (['', 'second line'], '', True), (['non-space', 'second line'], 'non-space', False), ([' ', 'second line'], '', True), ([' non-space', 'second line'], 'non-space', False), ] for lines, remaining_part, is_at_eol in test_cases: with self.subTest(): first_line = lines[0] source_lines = '\n'.join(lines) # ACT # source = ParseSource(source_lines) # ASSERT # source.consume_initial_space_on_current_line() assertion = assert_source(is_at_eol=asrt.equals(is_at_eol), remaining_part_of_current_line=asrt.equals(remaining_part), current_line_number=asrt.equals(1), current_line_text=asrt.equals(lines[0]), column_index=asrt.equals(len(first_line) - len(first_line.lstrip())) ) assertion.apply(self, source) def test_consume_with_invalid_arguments(self): test_cases = [ ('a', 0, 2), ('a', 1, 1), ('a\nb', 0, 4), ('a\nb', 1, 3), ] for source, num_chars_on_current_line_to_consume_before_check, num_chars in test_cases: with self.subTest(source=source, num_chars=num_chars): source = ParseSource(source) source.consume_part_of_current_line(num_chars_on_current_line_to_consume_before_check) with self.assertRaises(ValueError): source.consume(num_chars) def test_consume_with_valid_arguments(self): test_cases = [ (TestSetupForConsume('one whole line and part of next, with one line remaining', source_lines=['123', '45', '6'], number_of_characters_to_consume_from_current_line_before_test=0, number_of_characters_to_consume=4 + 1), assert_source(is_at_eof=asrt.equals(False), is_at_eol=asrt.equals(False), is_at_eol__except_for_space=asrt.equals(False), has_current_line=asrt.equals(True), current_line_number=asrt.equals(2), current_line_text=asrt.equals('45'), column_index=asrt.equals(1), remaining_part_of_current_line=asrt.equals('5'), remaining_source=asrt.equals('5\n6'))), (TestSetupForConsume('one whole line and part of next, with one line remaining, on column index 1', source_lines=['123', '45', '6'], number_of_characters_to_consume_from_current_line_before_test=1, number_of_characters_to_consume=4 + 1 - 1), assert_source(is_at_eof=asrt.equals(False), is_at_eol=asrt.equals(False), is_at_eol__except_for_space=asrt.equals(False), has_current_line=asrt.equals(True), current_line_number=asrt.equals(2), current_line_text=asrt.equals('45'), column_index=asrt.equals(1), remaining_part_of_current_line=asrt.equals('5'), remaining_source=asrt.equals('5\n6'))), (TestSetupForConsume('two whole lines, with one line remaining', source_lines=['123', '45', '6'], number_of_characters_to_consume_from_current_line_before_test=0, number_of_characters_to_consume=5 + 1), assert_source(is_at_eof=asrt.equals(False), is_at_eol=asrt.equals(True), is_at_eol__except_for_space=asrt.equals(True), has_current_line=asrt.equals(True), current_line_number=asrt.equals(2), current_line_text=asrt.equals('45'), column_index=asrt.equals(2), remaining_part_of_current_line=asrt.equals(''), remaining_source=asrt.equals('\n6'))), (TestSetupForConsume('two whole lines, with one line remaining, on column index 2', source_lines=['123', '45', '6'], number_of_characters_to_consume_from_current_line_before_test=2, number_of_characters_to_consume=5 + 1 - 2), assert_source(is_at_eof=asrt.equals(False), is_at_eol=asrt.equals(True), is_at_eol__except_for_space=asrt.equals(True), has_current_line=asrt.equals(True), current_line_number=asrt.equals(2), current_line_text=asrt.equals('45'), column_index=asrt.equals(2), remaining_part_of_current_line=asrt.equals(''), remaining_source=asrt.equals('\n6'))), (TestSetupForConsume('two whole lines, with no line after', source_lines=['123', '45'], number_of_characters_to_consume_from_current_line_before_test=0, number_of_characters_to_consume=5 + 1), assert_source(is_at_eof=asrt.equals(True), is_at_eol=asrt.equals(True), is_at_eol__except_for_space=asrt.equals(True), has_current_line=asrt.equals(True), current_line_number=asrt.equals(2), current_line_text=asrt.equals('45'), remaining_part_of_current_line=asrt.equals(''), remaining_source=asrt.equals(''))), (TestSetupForConsume('two whole lines, with no line after, on column index 3', source_lines=['123', '45'], number_of_characters_to_consume_from_current_line_before_test=3, number_of_characters_to_consume=5 + 1 - 3), assert_source(is_at_eof=asrt.equals(True), is_at_eol=asrt.equals(True), is_at_eol__except_for_space=asrt.equals(True), has_current_line=asrt.equals(True), current_line_number=asrt.equals(2), current_line_text=asrt.equals('45'), column_index=asrt.equals(2), remaining_part_of_current_line=asrt.equals(''), remaining_source=asrt.equals(''))), ] for setup, assertion in test_cases: with self.subTest(case_name=setup.name): source_lines = '\n'.join(setup.source_lines) source = ParseSource(source_lines) source.consume_part_of_current_line(setup.number_of_characters_to_consume_from_current_line_before_test) source.consume(setup.number_of_characters_to_consume) assertion.apply(self, source, asrt.MessageBuilder(setup.name)) def test_catch_up_with(self): test_cases = [ ('consume part of current line', ['abc'], lambda parse_source: parse_source.consume(1), lambda parse_source: parse_source.consume(2) ), ('copy consumes current line/with existing following line', ['abc', 'def'], lambda parse_source: None, lambda parse_source: parse_source.consume_current_line() ), ('copy consumes current line/which is the last line', ['abc'], lambda parse_source: None, lambda parse_source: parse_source.consume_current_line() ), ('copy consumes num characters that stretches to the following line', ['123', '456'], lambda parse_source: None, lambda parse_source: parse_source.consume(5) ), ('copy consumes all remaining characters', ['123', '456'], lambda parse_source: None, lambda parse_source: parse_source.consume(7) ), ] for test_name, original_source_lines, original_setup, copy_modifier in test_cases: with self.subTest(test_name): # ARRANGE # original = ParseSource('\n'.join(original_source_lines)) original_setup(original) # ACT # copy = original.copy copy_modifier(copy) original.catch_up_with(copy) # ASSERT # self.assertEqual(copy.is_at_eof, original.is_at_eof, 'is_at_eof') self.assertEqual(copy.remaining_source, original.remaining_source, 'remaining_source') self.assertEqual(copy.has_current_line, original.has_current_line, 'has_current_line') if original.has_current_line: self.assertEqual(copy.current_line_number, original.current_line_number, 'current_line_number') self.assertEqual(copy.remaining_part_of_current_line, original.remaining_part_of_current_line, 'remaining_part_of_current_line') self.assertEqual(copy.column_index, original.column_index, 'column_index') self.assertEqual(copy.is_at_eol, original.is_at_eol, 'is_at_eol')
def test_construction(self): test_cases = [ ('single line', assert_source(is_at_eof=asrt.is_false, is_at_eol=asrt.is_false, is_at_eol__except_for_space=asrt.is_false, has_current_line=asrt.is_true, column_index=asrt.equals(0), current_line_number=asrt.equals(1), current_line_text=asrt.equals('single line')) ), ('', assert_source(is_at_eof=asrt.is_true, is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, has_current_line=asrt.is_true, column_index=asrt.equals(0), current_line_number=asrt.equals(1), current_line_text=asrt.equals('')) ), ('first line\nsecond line', assert_source(is_at_eof=asrt.is_false, is_at_eol=asrt.is_false, is_at_eol__except_for_space=asrt.is_false, has_current_line=asrt.is_true, column_index=asrt.equals(0), current_line_number=asrt.equals(1), current_line_text=asrt.equals('first line')) ), ('single line\n', assert_source(is_at_eof=asrt.is_false, is_at_eol=asrt.is_false, is_at_eol__except_for_space=asrt.is_false, has_current_line=asrt.is_true, column_index=asrt.equals(0), current_line_number=asrt.equals(1), current_line_text=asrt.equals('single line')) ), ('\n', assert_source(is_at_eof=asrt.is_false, is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, has_current_line=asrt.is_true, column_index=asrt.equals(0), current_line_number=asrt.equals(1), current_line_text=asrt.equals('')) ), ('\nsecond line', assert_source(is_at_eof=asrt.is_false, is_at_eol=asrt.is_true, is_at_eol__except_for_space=asrt.is_true, has_current_line=asrt.is_true, column_index=asrt.equals(0), current_line_number=asrt.equals(1), current_line_text=asrt.equals('')) ), ] for source_string, expectation in test_cases: with self.subTest(msg='construction:' + repr(source_string)): source = ParseSource(source_string) expectation.apply_with_message(self, source, 'construction:{}'.format(repr(source_string)))