def __init__(self): super().__init__(syntax_elements.PATH_SYNTAX_ELEMENT) self._file_name = instruction_arguments.FILE_NAME_STRING self._relativity_name = instruction_arguments.RELATIVITY_ARGUMENT path_type_symbol = 'MY_PATH_SYMBOL' self._parser = TextParser({ 'Note': headers.NOTE_LINE_HEADER, 'RELATIVITY_OPTION': self._relativity_name.name, 'PATH_STRING': self._file_name.name, 'posix_syntax': documentation_text.POSIX_SYNTAX, 'string_type': formatting.keyword(types.STRING_TYPE_INFO.name.singular), 'string_type_plain': types.STRING_TYPE_INFO.name, 'reserved_word': misc_texts.RESERVED_WORD_NAME, 'reserved_word_list_str': ', '.join([formatting.keyword(x) for x in reserved_words.RESERVED_TOKENS]), 'path_type': formatting.keyword(types.PATH_TYPE_INFO.name.singular), 'string_syntax_element': syntax_elements.STRING_SYNTAX_ELEMENT.singular_name, 'cd': formatting.concept_(concepts.CURRENT_WORKING_DIRECTORY_CONCEPT_INFO), 'symbol': formatting.concept_(concepts.SYMBOL_CONCEPT_INFO), 'SYMBOL_NAME': syntax_elements.SYMBOL_NAME_SYNTAX_ELEMENT.argument.name, 'define_symbol': formatting.InstructionName(instruction_names.SYMBOL_DEFINITION_INSTRUCTION_NAME), 'current_directory': formatting.concept_(concepts.CURRENT_WORKING_DIRECTORY_CONCEPT_INFO), 'REFERENCED_SYMBOL': path_type_symbol, 'SYMBOL_REFERENCE': symbol_reference_syntax_for_name(path_type_symbol), 'def_of_path_symbol': define_symbol.def_syntax_string(ValueType.PATH, path_type_symbol, '...'), 'ref_of_path_symbol': '... ' + str(PurePosixPath(symbol_reference_syntax_for_name(path_type_symbol)) / 'a' / 'path' / 'relative' / 'to' / path_type_symbol), })
def test_fail(self): symbol_name = 'the_symbol_name' for grammar_description, grammar in GRAMMARS: cases = [ NameAndValue( 'symbol name is quoted', remaining_source( str(surrounded_by_hard_quotes(symbol_name))), ), NameAndValue( 'symbol reference syntax with invalid symbol name character: space', remaining_source( symbol_reference_syntax_for_name('the symbol')), ), NameAndValue( 'symbol reference syntax with invalid symbol name character: &', remaining_source( symbol_reference_syntax_for_name('the&symbol')), ), ] for case in cases: with self.subTest(grammar=grammar_description, case_name=case.name): parser = self.parser_maker.make( grammar, must_be_on_current_line=True) with self.assertRaises( SingleInstructionInvalidArgumentException): parser.parse(case.value)
def __init__(self): super().__init__(TypeCategory.DATA, syntax_elements.PATH_SYNTAX_ELEMENT) self._string_name = a.Named(syntax_elements.STRING_SYNTAX_ELEMENT.singular_name) self._relativity_name = instruction_arguments.RELATIVITY_ARGUMENT path_type_symbol = 'MY_PATH_SYMBOL' self._parser = TextParser({ 'RELATIVITY_OPTION': self._relativity_name.name, 'PATH_STRING': self._string_name.name, 'posix_syntax': documentation_text.POSIX_SYNTAX, 'string_type': formatting.keyword(types.STRING_TYPE_INFO.name.singular), 'path_type': formatting.keyword(types.PATH_TYPE_INFO.name.singular), 'string_syntax_element': syntax_elements.STRING_SYNTAX_ELEMENT.singular_name, 'cd': formatting.concept_(concepts.CURRENT_WORKING_DIRECTORY_CONCEPT_INFO), 'symbol': formatting.concept_(concepts.SYMBOL_CONCEPT_INFO), 'SYMBOL_NAME': syntax_elements.SYMBOL_NAME_SYNTAX_ELEMENT.argument.name, 'define_symbol': formatting.InstructionName(instruction_names.SYMBOL_DEFINITION_INSTRUCTION_NAME), 'current_directory': formatting.concept_(concepts.CURRENT_WORKING_DIRECTORY_CONCEPT_INFO), 'REFERENCED_SYMBOL': path_type_symbol, 'SYMBOL_REFERENCE': symbol_reference_syntax_for_name(path_type_symbol), 'def_of_path_symbol': define_symbol.def_syntax_string(ValueType.PATH, path_type_symbol, '...'), 'ref_of_path_symbol': '... ' + str(PurePosixPath(symbol_reference_syntax_for_name(path_type_symbol)) / 'a' / 'path' / 'relative' / 'to' / path_type_symbol), })
def cases_w_constant_contents() -> Sequence[Case]: here_doc_contents = 'single line in here doc\n' return [ Case( 'plain string', PlainStringAbsStx(StringLiteralAbsStx('the_string_value')), 'the_string_value', ), Case( 'empty string', PlainStringAbsStx(StringLiteralAbsStx.empty_string()), '', ), Case( 'sym ref syntax within hard quoted', PlainStringAbsStx( StringLiteralAbsStx( symbol_syntax.symbol_reference_syntax_for_name( A_VALID_SYMBOL_NAME), QuoteType.HARD)), symbol_syntax.symbol_reference_syntax_for_name( A_VALID_SYMBOL_NAME), ), Case( 'here doc start within quotes', PlainStringAbsStx( StringLiteralAbsStx(here_doc.here_doc_start_token('MARKER'), quoting_=QuoteType.SOFT)), here_doc.here_doc_start_token('MARKER'), ), Case( 'here doc', rich_str_abs_stx.HereDocAbsStx(here_doc_contents), here_doc_contents, ), ]
def _test_symbol_reference_in_dst_file_and_contents( self, symbol_ref_syntax_2_contents_arguments: Callable[[str], ArgumentElements], symbol_value_2_expected_contents: Callable[[str], str] ): sub_dir_name = 'sub-dir' relativity = RelOptionType.REL_ACT file_symbol = NameAndValue('file_symbol_name', file_refs.of_rel_option(relativity, file_refs.constant_path_part(sub_dir_name))) contents_symbol = NameAndValue('contents_symbol_name', 'contents symbol value') expected_file_symbol_reference = SymbolReference( file_symbol.name, parse_file_ref.path_or_string_reference_restrictions( ACCEPTED_RELATIVITY_VARIANTS)) expected_contents_symbol_reference = SymbolReference( contents_symbol.name, is_any_data_type()) expected_file_contents = symbol_value_2_expected_contents(contents_symbol.value) expected_file = fs.File('a-file-name.txt', expected_file_contents) expected_symbol_references = [expected_file_symbol_reference, expected_contents_symbol_reference] symbol_table = data_symbol_utils.SymbolTable({ file_symbol.name: data_symbol_utils.file_ref_constant_container(file_symbol.value), contents_symbol.name: data_symbol_utils.string_constant_container(contents_symbol.value), }) contents_arguments = symbol_ref_syntax_2_contents_arguments( symbol_reference_syntax_for_name(contents_symbol.name)).as_arguments assert isinstance(contents_arguments, Arguments) self._check( remaining_source( '{symbol_ref}/{file_name} {contents}'.format( symbol_ref=symbol_reference_syntax_for_name(file_symbol.name), file_name=expected_file.file_name, contents=contents_arguments.first_line ), contents_arguments.following_lines), ArrangementWithSds( pre_contents_population_action=SETUP_CWD_INSIDE_SDS_BUT_NOT_A_SDS_DIR, symbols=symbol_table, ), Expectation( main_result=IS_SUCCESS, symbol_usages=equals_symbol_references(expected_symbol_references), main_side_effects_on_sds=dir_contains_exactly( relativity, fs.DirContents([ fs.Dir(sub_dir_name, [expected_file])])), ))
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_multiple_symbol_references_in_executable(self): sub_dir_of_home = 'sub-dir' dir_symbol = NameAndValue('dir_symbol_name', file_refs.rel_home_act(file_refs.constant_path_part(sub_dir_of_home))) executable_file_name_symbol = NameAndValue('executable_file_name_symbol_name', 'the-executable-file') argument = 'argument_string' expected_output = lines_content([argument]) command_line = '{dir}/{file_name} {argument} '.format( dir=symbol_reference_syntax_for_name(dir_symbol.name), file_name=symbol_reference_syntax_for_name(executable_file_name_symbol.name), argument=argument, ) executable_file = fs.python_executable_file( executable_file_name_symbol.value, PYTHON_PROGRAM_THAT_PRINTS_COMMAND_LINE_ARGUMENTS_ON_SEPARATE_LINES) arrangement = Arrangement( hds_contents=contents_in(RelHomeOptionType.REL_HOME_ACT, fs.DirContents([ fs.Dir(sub_dir_of_home, [executable_file]) ])), symbol_table=SymbolTable({ dir_symbol.name: su.file_ref_constant_container(dir_symbol.value), executable_file_name_symbol.name: su.string_constant_container(executable_file_name_symbol.value), }) ) expectation = Expectation( result_of_execute=eh_assertions.is_exit_code(0), sub_process_result_from_execute=pr.stdout(asrt.Equals(expected_output, 'CLI arguments, one per line')), symbol_usages=equals_symbol_references([ SymbolReference(dir_symbol.name, path_or_string_reference_restrictions(PATH_RELATIVITY_VARIANTS_FOR_FILE_TO_RUN)), SymbolReference(executable_file_name_symbol.name, PATH_COMPONENT_STRING_REFERENCES_RESTRICTION), ]), ) check_execution(self, sut.Parser(), [instr([command_line])], 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 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 test_value_SHOULD_be_able_to_have_symbol_references(self): # ARRANGE # variable_name = 'variable_to_assign' my_symbol = StringConstantSymbolContext('my_symbol', 'my symbol value') your_symbol = StringConstantSymbolContext('your_symbol', 'your symbol value') value_template = 'pre {MY_SYMBOL} {YOUR_SYMBOL} post' expected_evaluated_value_string = value_template.format( MY_SYMBOL=my_symbol.str_value, YOUR_SYMBOL=your_symbol.str_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_syntax = SetVariableArgumentsAbsStx.of_str( variable_name, value_source_string, phase_spec=None, quoting=QuoteType.SOFT) # ACT & ASSERT # CHECKER.check__abs_stx__std_layouts_and_source_variants( self, source_syntax, Arrangement.setup_phase_aware( symbols=SymbolContext.symbol_table_of_contexts( [my_symbol, your_symbol]), process_execution_settings=ProcessExecutionSettings. with_environ({}), ), MultiSourceExpectation.setup_phase_aware( main_side_effect_on_environment_variables=asrt.equals( expected_environ_after_main), symbol_usages=asrt.matches_sequence([ my_symbol.usage_assertion__w_str_rendering, your_symbol.usage_assertion__w_str_rendering, ]), ), )
def runTest(self): to_upper_transformer = NameAndValue('TRANSFORMER_SYMBOL', StringTransformerResolverConstantTestImpl(MyToUppercaseTransformer())) src_file = fs.File('src-file.txt', 'contents of source file') src_file_symbol = NameAndValue('SRC_FILE_SYMBOL', src_file.name) expected_dst_file = fs.File('dst-file-name.txt', src_file.contents.upper()) dst_file_symbol = NameAndValue('DST_FILE_SYMBOL', expected_dst_file.name) file_contents_arg = arguments.TransformableContentsConstructor( arguments.file_with_rel_opt_conf(symbol_reference_syntax_for_name(src_file_symbol.name)) ).with_transformation(to_upper_transformer.name).as_arguments source = remaining_source( '{file_name} {content_arguments}'.format( file_name=symbol_reference_syntax_for_name(dst_file_symbol.name), content_arguments=file_contents_arg.first_line ), file_contents_arg.following_lines) # ACT # instruction = self.conf.parser().parse(ARBITRARY_FS_LOCATION_INFO, source) assert isinstance(instruction, TestCaseInstructionWithSymbols) # Sanity check # ASSERT # expected_symbol_usages = [ equals_symbol_reference( SymbolReference(dst_file_symbol.name, file_ref_or_string_reference_restrictions( new_file.REL_OPT_ARG_CONF.options.accepted_relativity_variants)) ), is_reference_to_string_transformer(to_upper_transformer.name), equals_symbol_reference( SymbolReference(src_file_symbol.name, file_ref_or_string_reference_restrictions( parse_file_maker._src_rel_opt_arg_conf_for_phase( self.conf.phase_is_after_act()).options.accepted_relativity_variants)) ), ] expected_symbol_references = asrt.matches_sequence(expected_symbol_usages) expected_symbol_references.apply_without_message(self, instruction.symbol_usages())
def test_string_token(self): # ARRANGE # plain_string = 'plain' symbol_name = 'symbol_name' cases = [ Case('plain string', plain_string, Expectation( elements=[list_resolvers.str_element(plain_string)], validators=asrt.is_empty_sequence, references=asrt.is_empty_sequence, )), Case('symbol reference', symbol_reference_syntax_for_name(symbol_name), Expectation( elements=[list_resolvers.symbol_element(symbol_reference(symbol_name))], validators=asrt.is_empty_sequence, references=asrt.matches_sequence([asrt_sym_ref.matches_reference_2( symbol_name, is_any_data_type_reference_restrictions()) ]), )), ] # ACT & ASSERT # _test_cases(self, cases)
def test_definition_and_reference_in_definition(self): leaf_name = 'LEAF_SYMBOL_SYMBOL' referrer_name = 'REFERRER_SYMBOL' case_with_single_def = File( 'test.case', lines_content([ phase_names.SETUP.syntax, sym_def.define_string(leaf_name, 'value'), sym_def.define_string(referrer_name, symbol_reference_syntax_for_name(leaf_name)), ])) test_with_files_in_tmp_dir.check( self, command_line_arguments= symbol_args.arguments([case_with_single_def.name]), arrangement= Arrangement( cwd_contents=DirContents([ case_with_single_def, ]), main_program_config=sym_def.main_program_config(), ), expectation= asrt_proc_result.sub_process_result( exitcode=asrt.equals(exit_codes.EXIT_OK), stdout=asrt.equals(output.list_of([ output.SymbolReport(leaf_name, ValueType.STRING, num_refs=1), output.SymbolReport(referrer_name, ValueType.STRING, num_refs=0), ])), ) )
def test_name_of_symbol_WHEN_valid_symbol_name_surrounded_by_symbol_reference_markers( self): # ACT # actual = sut.parse_maybe_symbol_reference( sut.symbol_reference_syntax_for_name(A_VALID_SYMBOL_NAME)) # ASSERT # self.assertEqual(A_VALID_SYMBOL_NAME, actual)
def test_resolving_object_with_different_symbol_values_SHOULD_give_different_values(self): # ARRANGE # STRING_SYMBOL_NAME = 'STRING_SYMBOL' single_sym_ref_source = remaining_source(symbol_reference_syntax_for_name(STRING_SYMBOL_NAME)) actual_resolver = sut.parse_regex(single_sym_ref_source) non_matching_string = '0' for symbol_value in ['A', 'B']: with self.subTest(symbol_value=symbol_value): symbols = SymbolTable({ STRING_SYMBOL_NAME: container(string_resolvers.str_constant(symbol_value)), }) # ACT & ASSERT # self._assert_resolved_pattern_has_pattern_string( actual_resolver, expected_pattern_string=symbol_value, matching_string=symbol_value, non_matching_string=non_matching_string, symbols=symbols, )
def test_single_definition_with_reference_to_builtin_symbol(self): builtin_symbol = StringSymbolContext.of_constant( 'BUILTIN_STRING_SYMBOL', 'builtin string symbol value') user_defined_symbol_name = 'STRING_SYMBOL' case_with_single_def = File( 'test.xly', lines_content([ phase_names.SETUP.syntax, sym_def.define_string( user_defined_symbol_name, symbol_reference_syntax_for_name(builtin_symbol.name)), ])) check_case_and_suite( self, symbol_command_arguments=[case_with_single_def.name], arrangement=Arrangement( cwd_contents=DirContents([ case_with_single_def, ]), main_program_config=sym_def.main_program_config( builtin_symbols=[ sym_def.builtin_symbol(builtin_symbol), ]), ), expectation=asrt_proc_result.sub_process_result( exitcode=asrt.equals(exit_codes.EXIT_OK), stdout=asrt.equals( output.list_of([ output.SymbolSummary(user_defined_symbol_name, ValueType.STRING, num_refs=0), ])), ))
def test_with_symbol_references(self): symbol1 = NameAndValue('symbol_1_name', 'symbol 1 value') line_with_sym_ref_template = 'before symbol {symbol} after symbol' source = remaining_source_lines(['<<MARKER', line_with_sym_ref_template.format( symbol=symbol_reference_syntax_for_name(symbol1.name)), 'MARKER', 'Line 4', ] ) expectation = ExpectedHereDoc( resolved_here_doc_lines=[ line_with_sym_ref_template.format( symbol=symbol1.value) ], common=CommonExpectation( symbol_references=[ references.reference_to_any_data_type_value(symbol1.name), ], symbol_table=symbol_table_with_string_values_from_name_and_value([ symbol1, ]), source=asrt_source.is_at_beginning_of_line(4), ) ) _expect_here_doc(self, source, expectation)
def _test_symbol_reference_in_contents( self, symbol_ref_syntax_2_contents_arguments: Callable[ [str], StringSourceAbsStx], symbol_value_2_expected_contents: Callable[[str], str]): contents_symbol = StringConstantSymbolContext( 'contents_symbol_name', 'contents symbol value', default_restrictions=asrt_rest.is__w_str_rendering(), ) expected_contents = symbol_value_2_expected_contents( contents_symbol.str_value) symbols = [contents_symbol] expected_symbol_references = SymbolContext.references_assertion_of_contexts( symbols) symbol_table = SymbolContext.symbol_table_of_contexts(symbols) string_source_syntax = symbol_ref_syntax_2_contents_arguments( symbol_reference_syntax_for_name(contents_symbol.name)) CHECKER.check__abs_stx( self, string_source_syntax, None, arrangement_w_tcds(symbols=symbol_table, ), Expectation.of_prim__const( primitive=asrt_string_source. pre_post_freeze__matches_str__const( expected_contents, may_depend_on_external_resources=False), parse=ParseExpectation( symbol_references=expected_symbol_references, ), ))
def test_symbols_from_comparison_SHOULD_be_reported(self): # ARRANGE # operand_sym_ref = SymbolReference('operand_symbol_name', string_made_up_by_just_strings()) condition_str = '{operator} {symbol_reference}'.format( operator=comparators.EQ.name, symbol_reference=symbol_reference_syntax_for_name(operand_sym_ref.name) ) arguments_constructor = args.complete_arguments_constructor( NumFilesAssertionVariant(condition_str)) argument = arguments_constructor.apply(expectation_type_config__non_is_success(ExpectationType.NEGATIVE)) source = remaining_source(argument) # ACT # actual_matcher = sut.files_matcher_parser().parse(source) assert isinstance(actual_matcher, FilesMatcherResolver) actual_symbol_references = actual_matcher.references # ASSERT # expected_symbol_references = [ operand_sym_ref, ] assertion = equals_symbol_references(expected_symbol_references) assertion.apply_without_message(self, actual_symbol_references)
def test_definition_and_reference_in_definition(self): leaf_name = 'LEAF_SYMBOL_SYMBOL' referrer_name = 'REFERRER_SYMBOL' case_with_single_def = File( 'test.xly', lines_content([ phase_names.SETUP.syntax, sym_def.define_string(leaf_name, 'value'), sym_def.define_string( referrer_name, symbol_reference_syntax_for_name(leaf_name)), ])) check_case_and_suite( self, symbol_command_arguments=[case_with_single_def.name], arrangement=Arrangement( cwd_contents=DirContents([ case_with_single_def, ]), main_program_config=sym_def.main_program_config(), ), expectation=asrt_proc_result.sub_process_result( exitcode=asrt.equals(exit_codes.EXIT_OK), stdout=asrt.equals( output.list_of([ output.SymbolSummary(leaf_name, ValueType.STRING, num_refs=1), output.SymbolSummary(referrer_name, ValueType.STRING, num_refs=0), ])), ))
def test_symbol_reference_on_command_line_SHOULD_be_reported_and_used_in_execution(self): symbol = NameAndValue('symbol_name', 'symbol value') string_to_print_template = 'constant and {symbol}' expected_output_template = string_to_print_template + '\n' shell_source_line = shell_commands.command_that_prints_to_stdout( string_to_print_template.format(symbol=symbol_reference_syntax_for_name(symbol.name)) ) act_phase_instructions = [instr([shell_command_source_line_for(shell_source_line)])] expected_symbol_references = [ SymbolReference(symbol.name, is_any_data_type()), ] check_execution( self, sut.Parser(), act_phase_instructions, Arrangement( symbol_table=SymbolTable({ symbol.name: data_symbol_utils.string_constant_container(symbol.value) }) ), Expectation( symbol_usages=equals_symbol_references(expected_symbol_references), sub_process_result_from_execute= pr.stdout(asrt.equals(expected_output_template.format(symbol=symbol.value))) ), )
def runTest(self): actual_line_num = 3 int_string_symbol = NameAndValue( 'int_string_symbol_name', string_resolvers.str_constant(str(actual_line_num)) ) arguments = arg.LineNum(int_condition__expr(comparators.EQ, symbol_reference_syntax_for_name(int_string_symbol.name))) model_that_matches = (actual_line_num, 'the line') integration_check.check( self, source= remaining_source(str(arguments)), model=model_that_matches, arrangement= integration_check.Arrangement( symbols=symbol_utils.symbol_table_from_name_and_resolvers([int_string_symbol]) ), expectation= integration_check.Expectation( symbol_references=asrt.matches_sequence([ is_reference_to_symbol_in_expression(int_string_symbol.name) ]), ) )
def runTest(self): path_suffix = 'the-path-suffix' symbol = NameAndValue('symbol_name', file_refs.rel_act(file_refs.constant_path_part(path_suffix))) program_that_prints_value_of_symbol = 'print("{symbol}")' single_source_line = program_that_prints_value_of_symbol.format( symbol=symbol_reference_syntax_for_name(symbol.name), ) self._check( single_source_line, Arrangement( symbol_table=SymbolTable({ symbol.name: su.file_ref_constant_container(symbol.value), }) ), Expectation( symbol_usages=equals_symbol_references([ SymbolReference(symbol.name, is_any_data_type()), ]), sub_process_result_from_execute=pr.stdout(str_asrt.contains(path_suffix)), ))
def test_result_SHOULD_be_true_iff_exit_code_is_0(self): # ARRANGE # program_symbol_name = 'PROGRAM_THAT_EXECUTES_PY_FILE' exit_code_symbol_name = 'EXIT_CODE_SYMBOL' # ACT && ASSERT # integration_check.CHECKER__PARSE_FULL.check_multi( self, args.RunProgram( program_args.symbol_ref_command_elements( program_symbol_name, arguments=[ symbol_reference_syntax_for_name(exit_code_symbol_name) ], )).as_arguments, ParseExpectation( source=asrt_source.is_at_end_of_line(1), symbol_references=asrt.matches_sequence([ is_reference_to_program(program_symbol_name), is_reference_to__w_str_rendering(exit_code_symbol_name), ]), ), integration_check.ARBITRARY_MODEL, test_cases.exit_code_exe_cases( program_symbol_name, exit_code_symbol_name, ), )
def runTest(self): actual_contents = lines_content(['1', '2', '3', '4']) symbol_value = '3' constant_value = '1' operand_symbol = StringSymbolContext.of_constant( 'operand_symbol', symbol_value) expression_that_evaluates_to_actual_number_of_lines = '{sym_ref}+{const}'.format( sym_ref=symbol_reference_syntax_for_name(operand_symbol.name), const=constant_value, ) symbol_table_with_operand_symbol = operand_symbol.symbol_table expected_symbol_usages = asrt.matches_sequence( [is_reference_to_symbol_in_expression(operand_symbol.name)]) self._check_variants_with_expectation_type( InstructionArgumentsVariantConstructor( operator=comparators.GTE.name, operand=expression_that_evaluates_to_actual_number_of_lines), expected_result_of_positive_test=PassOrFail.PASS, actual_file_contents=actual_contents, symbols=symbol_table_with_operand_symbol, expected_symbol_references=expected_symbol_usages, )
def runTest(self): symbol = NameAndValue('symbol_name', 'the symbol value') program_that_prints_value_of_symbol = 'print("{symbol}")' single_source_line = program_that_prints_value_of_symbol.format( symbol=symbol_reference_syntax_for_name(symbol.name), ) expected_output = symbol.value + '\n' self._check( single_source_line, Arrangement( symbol_table=SymbolTable({ symbol.name: su.string_constant_container(symbol.value), }) ), Expectation( symbol_usages=equals_symbol_references([ SymbolReference(symbol.name, is_any_data_type()), ]), sub_process_result_from_execute=pr.stdout(asrt.Equals(expected_output, 'program output')), ))
def test_raise_exception_WHEN_invalid_assertion_variant(self): parser = sut.parser.Parser() cases = [ NameAndValue( 'valid file argument, but no operator', args.complete_arguments_constructor( 'file-name', InvalidAssertionVariantArgumentsConstructor('') ), ), NameAndValue( 'valid file argument, invalid check', args.complete_arguments_constructor( 'file-name', InvalidAssertionVariantArgumentsConstructor(symbol_reference_syntax_for_name('invalidCheck')) ), ), ] for case in cases: for rel_opt_config in [tr.DEFAULT_REL_OPT_CONFIG, tr.ARBITRARY_ACCEPTED_REL_OPT_CONFIG]: for expectation_type in ExpectationType: etc = pfh_expectation_type_config(expectation_type) instruction_arguments = case.value.apply(etc, rel_opt_config) with self.subTest(case_name=case.name, expectation_type=str(expectation_type)): for source in equivalent_source_variants(self, instruction_arguments): with self.assertRaises(SingleInstructionInvalidArgumentException): parser.parse(ARBITRARY_FS_LOCATION_INFO, source)
def runTest(self): actual_contents = lines_content(['1', '2', '3', '4']) symbol_value = '3' constant_value = '1' operand_symbol = NameAndValue('operand_symbol', string_resolvers.str_constant(symbol_value)) expression_that_evaluates_to_actual_number_of_lines = '{sym_ref}+{const}'.format( sym_ref=symbol_reference_syntax_for_name(operand_symbol.name), const=constant_value, ) symbol_table_with_operand_symbol = SymbolTable({ operand_symbol.name: container(operand_symbol.value) }) expected_symbol_usages = asrt.matches_sequence([ is_string_made_up_of_just_strings_reference_to(operand_symbol.name) ]) self._check_variants_with_expectation_type( InstructionArgumentsVariantConstructor( operator=comparators.GTE.name, operand=expression_that_evaluates_to_actual_number_of_lines), expected_result_of_positive_test=PassOrFail.PASS, actual_file_contents=actual_contents, symbols=symbol_table_with_operand_symbol, expected_symbol_usages=expected_symbol_usages, )
def _doTest(self, maybe_not: ExpectationTypeConfigForNoneIsSuccess): expected_content_line_template = 'expected content line, with {symbol} ref' def expected_content(symbol_content: str) -> str: return expected_content_line_template.format(symbol=symbol_content) symbol = NameAndValue('symbol_name', 'the symbol value') self._check( self.configuration.source_for( args('{maybe_not} {equals} <<EOF', maybe_not=maybe_not.nothing__if_positive__not_option__if_negative), [expected_content(symbol_reference_syntax_for_name(symbol.name)), 'EOF', 'following line']), model_construction.model_of(lines_content([expected_content(symbol.value)])), self.configuration.arrangement_for_contents( post_sds_population_action=MK_SUB_DIR_OF_ACT_AND_MAKE_IT_CURRENT_DIRECTORY, symbols=SymbolTable({ symbol.name: data_symbol_utils.string_constant_container(symbol.value), })), Expectation(main_result=maybe_not.pass__if_positive__fail__if_negative, symbol_usages=equals_symbol_references([ SymbolReference(symbol.name, is_any_data_type()) ]), source=asrt_source.is_at_end_of_line(3)), )
def layout( self, spec: LayoutSpec, position: AbstractSet[TokenPosition], ) -> Sequence[str]: return (symbol_syntax.symbol_reference_syntax_for_name( self._symbol_name), )
def test_resolving_object_with_different_symbol_values_SHOULD_give_different_values(self): # ARRANGE # STRING_SYMBOL_NAME = 'STRING_SYMBOL' single_sym_ref_source = remaining_source(symbol_reference_syntax_for_name(STRING_SYMBOL_NAME)) parser = sut.ParserOfRegex() # ACT # actual_sdv = parser.parse_from_token_parser(single_sym_ref_source) non_matching_string = '0' for symbol_value in ['A', 'B']: with self.subTest(symbol_value=symbol_value): string_symbol = StringSymbolContext.of_constant(STRING_SYMBOL_NAME, symbol_value) symbols = string_symbol.symbol_table # ASSERT # self._assert_resolved_pattern_has_pattern_string( actual_sdv, expected_pattern_string=symbol_value, matching_string=symbol_value, non_matching_string=non_matching_string, symbols=symbols, )
def test_with_symbol_references(self): symbol_1_name = 'symbol_1_name' symbol_2_name = 'symbol_2_name' test_cases = [ CaseWithSymbols( 'two argument form with a symbol that is a single integer', argument=' {op} {sym_ref}'.format(op=comparators.EQ.name, sym_ref=symbol_reference_syntax_for_name(symbol_1_name)), symbol_name_and_value_list=[NameAndValue(symbol_1_name, '72')], actual_value_for_pass=72, actual_value_for_fail=87, ), CaseWithSymbols( 'two argument form with two symbols that makes up the expected value when concatenated', argument=' {op} {sym_ref1}{sym_ref2}'.format( op=comparators.EQ.name, sym_ref1=symbol_reference_syntax_for_name(symbol_1_name), sym_ref2=symbol_reference_syntax_for_name(symbol_2_name)), symbol_name_and_value_list=[NameAndValue(symbol_1_name, '7'), NameAndValue(symbol_2_name, '2')], actual_value_for_pass=72, actual_value_for_fail=87, ), ] for case in test_cases: for sub_name, actual_value, result_expectation in [('pass', case.actual_value_for_pass, pfh_assertions.is_pass()), ('fail', case.actual_value_for_fail, pfh_assertions.is_fail())]: with self.subTest(name=case.name, sub_name=sub_name): self._run( remaining_source(case.argument, ['following line']), ArrangementPostAct( act_result_producer=act_result_of(actual_value), symbols=symbol_table_with_string_constant_symbols(case.symbol_name_and_value_list), ), Expectation( source=is_at_beginning_of_line(2), main_result=result_expectation, symbol_usages=equals_symbol_references( string_symbol_references_of(case.symbol_name_and_value_list)) ), )
def test_symbol_references(self): # ARRANGE # star_string_symbol = NameAndValue('STAR_SYMBOL', container(string_resolvers.str_constant('* '))) regex_str = '.* regex' regex_arg_str = '.{star}regex'.format( star=symbol_reference_syntax_for_name(star_string_symbol.name), ) matches_for_case_sensitive = [' regex', 'before regex after'] option_cases = [ option_case_for_no_option( _AssertPattern(regex_str, matching_strings=matches_for_case_sensitive, non_matching_string=' REGEX') ), option_case_for_ignore_case( _AssertPattern(regex_str, matching_strings=matches_for_case_insensitive(matches_for_case_sensitive), non_matching_string='regex') ), ] source_cases = [ SourceCase('single invalid star', Arguments(regex_arg_str), assert_token_stream(is_null=asrt.is_true) ), SourceCase('invalid stars at start of regex', Arguments(surrounded_by_soft_quotes(regex_arg_str)), assert_token_stream(is_null=asrt.is_true) ), ] arrangement = Arrangement( symbols=SymbolTable({ star_string_symbol.name: star_string_symbol.value, }) ) expectation = ExpectationExceptPattern( references=asrt.matches_sequence([ is_reference_to_valid_regex_string_part(star_string_symbol.name), ]), validation=all_validations_passes(), ) # ACT & ASSERT # check_many(self, arrangement, source_cases, expectation, option_cases, )
def test_symbol_references(self): # ARRANGE # star_string_symbol = StringSymbolContext.of_constant('STAR_SYMBOL', '* ') regex_str = '.* regex' regex_arg_str = '.{star}regex'.format( star=symbol_reference_syntax_for_name(star_string_symbol.name), ) matches_for_case_sensitive = [' regex', 'before regex after'] option_cases = [ option_case_for_no_option( _AssertPattern(regex_str, matching_strings=matches_for_case_sensitive, non_matching_string=' REGEX') ), option_case_for_ignore_case( _AssertPattern(regex_str, matching_strings=matches_for_case_insensitive(matches_for_case_sensitive), non_matching_string='regex') ), ] source_cases = [ SourceCase('single invalid star', Arguments(regex_arg_str), assert_token_stream(is_null=asrt.is_true) ), SourceCase('invalid stars at start of regex', Arguments(surrounded_by_soft_quotes(regex_arg_str)), assert_token_stream(is_null=asrt.is_true) ), ] arrangement = Arrangement( symbols=star_string_symbol.symbol_table ) expectation = ExpectationExceptPattern( references=asrt.matches_sequence([ is_reference_to__regex_string_part(star_string_symbol.name), ]), validation=ValidationAssertions.all_passes(), ) # ACT & ASSERT # check_many(self, arrangement, source_cases, expectation, option_cases, )
def successful_parse_of_constant() -> List[TC]: return [ TC( _src('plain-word1 plain-word2'), Expectation( fragments=[constant('plain-word1')], token_stream=assert_token_stream( head_token=assert_token_string_is('plain-word2')), )), TC( _src('word'), Expectation( fragments=[constant('word')], token_stream=assert_token_stream(is_null=asrt.is_true), )), TC( _src('{soft_quote}double quoted word{soft_quote} plain-word2', soft_quote=SOFT_QUOTE_CHAR), Expectation( fragments=[constant('double quoted word')], token_stream=assert_token_stream( head_token=assert_token_string_is('plain-word2')), )), TC( _src('{hard_quote}single quoted word{hard_quote} plain-word2', hard_quote=HARD_QUOTE_CHAR), Expectation( fragments=[constant('single quoted word')], token_stream=assert_token_stream( head_token=assert_token_string_is('plain-word2')), )), TC( _src('{hard_quote}{symbol_reference}{hard_quote} plain-word2', symbol_reference=symbol_reference_syntax_for_name('sym_name'), hard_quote=HARD_QUOTE_CHAR), Expectation( fragments=[ constant(symbol_reference_syntax_for_name('sym_name')) ], token_stream=assert_token_stream( head_token=assert_token_string_is('plain-word2')), )), ]
def __init__(self, name: str, value_int: int, value_str: str, ): self.name = name self.value_int = value_int self.value_str = value_str self.ref_syntax = symbol_reference_syntax_for_name(name) self.symbol_reference = data_symbol_utils.symbol_reference(name)
def failing_integer_validation_cases(symbol_in_integer_name: str = 'symbol_in_integer' ) -> Sequence[IntegerValidationCase]: non_int_string_symbol = StringSymbolContext.of_constant( symbol_in_integer_name, 'tre' ) non_iterable_string_symbol = StringSymbolContext.of_constant( symbol_in_integer_name, '1' ) constant_string_cases = [ IntegerValidationCase('failing validation/pre sds: ' + expr_str, expr_str, [], [], validation.PRE_SDS_FAILURE_EXPECTATION, validation.ValidationAssertions.pre_sds_fails__w_any_msg(), ) for expr_str in _PRE_SDS_VALIDATION_FAILURE__CONSTANT_STRINGS ] string_with_symbol_cases = [ IntegerValidationCase('failing validation/pre sds: non-int string ref', symbol_reference_syntax_for_name(non_int_string_symbol.name), [non_int_string_symbol], [is_reference_to_symbol_in_expression(non_int_string_symbol.name)], validation.PRE_SDS_FAILURE_EXPECTATION, ValidationAssertions.pre_sds_fails__w_any_msg(), ), IntegerValidationCase('failing validation/pre sds: non-iterable string ref', 'len({})'.format(symbol_reference_syntax_for_name(non_iterable_string_symbol.name)), [non_iterable_string_symbol], [is_reference_to_symbol_in_expression(non_iterable_string_symbol.name)], validation.PRE_SDS_FAILURE_EXPECTATION, ValidationAssertions.pre_sds_fails__w_any_msg(), ), ] return constant_string_cases + string_with_symbol_cases
def symbol_ref_syntax_cases(symbol_name: str) -> Sequence[NameAndValue[str]]: return [ NameAndValue( 'plain', symbol_name, ), NameAndValue( 'reference syntax', symbol_reference_syntax_for_name(symbol_name), ), ]
def runTest(self): symbol_for_source_file = NameAndValue('source_file_symbol_name', 'the-source-file.py') argument_symbol = NameAndValue('argument_symbol_name', 'string-constant') expected_output = lines_content([argument_symbol.value]) command_line = '{source_file} {argument} '.format( source_file=symbol_reference_syntax_for_name(symbol_for_source_file.name), argument=symbol_reference_syntax_for_name(argument_symbol.name), ) arrangement = Arrangement( hds_contents=contents_in(RelHomeOptionType.REL_HOME_ACT, fs.DirContents([ fs.File( symbol_for_source_file.value, PYTHON_PROGRAM_THAT_PRINTS_COMMAND_LINE_ARGUMENTS_ON_SEPARATE_LINES) ])), symbol_table=SymbolTable({ symbol_for_source_file.name: su.string_constant_container(symbol_for_source_file.value), argument_symbol.name: su.string_constant_container(argument_symbol.value), }) ) expectation = Expectation( result_of_execute=eh_assertions.is_exit_code(0), sub_process_result_from_execute=pr.stdout(asrt.Equals(expected_output, 'CLI arguments, one per line')), symbol_usages=equals_symbol_references([ SymbolReference(symbol_for_source_file.name, path_or_string_reference_restrictions(PATH_RELATIVITY_VARIANTS_FOR_FILE_TO_RUN)), SymbolReference(argument_symbol.name, is_any_data_type()), ]), ) self._check(command_line, arrangement, expectation)
def runTest(self): parser = self.configuration.new_parser() for maybe_with_transformer_option in TRANSFORMER_OPTION_ALTERNATIVES: with self.subTest(maybe_with_transformer_option=maybe_with_transformer_option): source = self.configuration.source_for( args('{maybe_with_transformer_option} {maybe_not} {symbol_reference}', maybe_with_transformer_option=maybe_with_transformer_option, maybe_not=self.maybe_not.nothing__if_positive__not_option__if_negative, symbol_reference=symbol_reference_syntax_for_name(SYMBOL_FOR_EMPTINESS_MATCHER.name)), ) with self.assertRaises(SingleInstructionInvalidArgumentException): parser.parse(ARBITRARY_FS_LOCATION_INFO, source)
def test_case(self) -> str: equals_builtin_symbol_value_matcher = str_matcher_args.Equals.eq_string( symbol_reference_syntax_for_name( self._name_of_checked_symbol)).as_arguments.as_single_string return lines_content([ pgm_args.interpret_py_source_file( self.PY_PROGRAM_FILE_NAME).as_str, phase_header_line(phase_identifier.ASSERT), ' '.join((instruction_names.CONTENTS_OF_STDOUT_INSTRUCTION_NAME, equals_builtin_symbol_value_matcher)), ])
def _doTest(self, maybe_not: ExpectationTypeConfigForNoneIsSuccess): parser = self.configuration.new_parser() for maybe_with_transformer_option in TRANSFORMER_OPTION_ALTERNATIVES: with self.subTest(maybe_with_transformer_option=maybe_with_transformer_option): source = self.configuration.source_for( args('{maybe_with_transformer_option} {maybe_not} {symbol_reference}', maybe_with_transformer_option=maybe_with_transformer_option, maybe_not=maybe_not.nothing__if_positive__not_option__if_negative, symbol_reference=symbol_reference_syntax_for_name(SYMBOL_FOR_EMPTINESS_MATCHER.name)), ) with self.assertRaises(SingleInstructionInvalidArgumentException): parser.parse(source)
def test_value_with_hard_quoted_value_SHOULD_skip_symbol_substitution( self): # ARRANGE # 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_syntax = SetVariableArgumentsAbsStx.of_str( variable_name, value_source_string, phase_spec=None, quoting=QuoteType.HARD) # ACT & ASSERT # CHECKER.check__abs_stx__std_layouts_and_source_variants( self, source_syntax, Arrangement.setup_phase_aware( process_execution_settings=ProcessExecutionSettings. with_environ({}), ), MultiSourceExpectation.setup_phase_aware( main_side_effect_on_environment_variables=asrt.equals( expected_environ_after_main), symbol_usages=asrt.matches_sequence([]), ), )
def test_None_WHEN_not_surrounded_by_symbol_reference_markers_or_not_a_valid_symbol_name( self): # ARRANGE # cases = [ NameAndValue( 'no markers at all - valid symbol name', A_VALID_SYMBOL_NAME, ), NameAndValue( 'no markers at all - invalid symbol name', NOT_A_VALID_SYMBOL_NAME, ), NameAndValue( 'markers at beginning, only', sut.SYMBOL_REFERENCE_BEGIN + A_VALID_SYMBOL_NAME, ), NameAndValue( 'markers at end, only', A_VALID_SYMBOL_NAME + sut.SYMBOL_REFERENCE_BEGIN, ), NameAndValue( 'markers at end, only', A_VALID_SYMBOL_NAME + sut.SYMBOL_REFERENCE_END, ), NameAndValue( 'invalid symbol name', sut.symbol_reference_syntax_for_name(NOT_A_VALID_SYMBOL_NAME), ), NameAndValue( 'two consecutive symbol references', (sut.symbol_reference_syntax_for_name(A_VALID_SYMBOL_NAME) + sut.symbol_reference_syntax_for_name(A_VALID_SYMBOL_NAME)), ), ] for case in cases: with self.subTest(case.name): # ACT # actual = sut.parse_maybe_symbol_reference(case.value) # ASSERT # self.assertIsNone(actual)
def __init__(self): super().__init__(SYMBOL_CONCEPT_INFO) list_symbol_name = 'LIST_SYMBOL' file_trans_symbol_name = 'REPLACE_ID' symbol_names = [ list_symbol_name, file_trans_symbol_name, ] self._parser = TextParser({ 'program_name': formatting.program_name(program_info.PROGRAM_NAME), 'symbol': SYMBOL_CONCEPT_INFO.name, 'instruction': concepts.INSTRUCTION_CONCEPT_INFO.name, 'symbol_name_syntax_element': syntax_elements.SYMBOL_NAME_SYNTAX_ELEMENT.argument.name, 'define_symbol': formatting.InstructionName( instruction_names.SYMBOL_DEFINITION_INSTRUCTION_NAME), 'symbol_name_syntax': syntax_descriptions.SYMBOL_NAME_SYNTAX_DESCRIPTION, 'def': instruction_names.SYMBOL_DEFINITION_INSTRUCTION_NAME, 'string_type_in_text': types.STRING_TYPE_INFO.name, 'string_type': types.VALUE_TYPE_2_TYPES_INFO_DICT[ValueType.STRING].identifier, 'list_type': types.VALUE_TYPE_2_TYPES_INFO_DICT[ValueType.LIST].identifier, 'file_trans_type': types.VALUE_TYPE_2_TYPES_INFO_DICT[ ValueType.STRING_TRANSFORMER].identifier, 'max_type_width': max( map(lambda type_info: len(type_info.identifier), types.VALUE_TYPE_2_TYPES_INFO_DICT.values())), 'LIST_SYMBOL': list_symbol_name, 'FILE_TRANS_SYMBOL': file_trans_symbol_name, 'max_symbol_name_width': max(map(len, symbol_names)), 'ref_syntax_of_symbol_name': symbol_reference_syntax_for_name('symbol_name'), 'exists_file': instruction_names.TEST_CASE_STATUS_INSTRUCTION_NAME, 'stdout': instruction_names.CONTENTS_OF_STDOUT_INSTRUCTION_NAME, 'transformed': string_transformer.STRING_TRANSFORMATION_ARGUMENT, })
def _test_symbol_reference_in_dst_file_and_contents( self, symbol_ref_syntax_2_contents_arguments: Callable[ [str], StringSourceAbsStx], symbol_value_2_expected_contents: Callable[[str], str]): sub_dir_symbol = ConstantSuffixPathDdvSymbolContext( 'sub_dir_symbol', RelOptionType.REL_ACT, 'sub-dir', ACCEPTED_DST_RELATIVITY_VARIANTS, ) contents_symbol = StringConstantSymbolContext( 'contents_symbol_name', 'contents symbol value', default_restrictions=asrt_rest.is__w_str_rendering(), ) expected_file_contents = symbol_value_2_expected_contents( contents_symbol.str_value) expected_file = fs.File('a-file-name.txt', expected_file_contents) symbols = [sub_dir_symbol, contents_symbol] expected_symbol_references = SymbolContext.references_assertion_of_contexts( symbols) symbol_table = SymbolContext.symbol_table_of_contexts(symbols) contents_arguments = symbol_ref_syntax_2_contents_arguments( symbol_reference_syntax_for_name(contents_symbol.name)) instruction_syntax = instr_abs_stx.create_w_explicit_contents( path_abs_stx.PathStringAbsStx.of_plain_components( [sub_dir_symbol.name__sym_ref_syntax, expected_file.name]), contents_arguments, ) integration_check.CHECKER__AFTER_ACT.check__abs_stx( self, instruction_syntax, Arrangement.phase_agnostic( tcds=TcdsArrangement( pre_population_action= SETUP_CWD_INSIDE_SDS_BUT_NOT_A_SDS_DIR__PLAIN, ), symbols=symbol_table, ), Expectation.phase_agnostic( main_result=IS_SUCCESS, symbol_usages=expected_symbol_references, main_side_effects_on_sds=dir_contains_exactly( sub_dir_symbol.rel_option_type, fs.DirContents( [fs.Dir(sub_dir_symbol.path_suffix, [expected_file])])), ))
def __init__( self, name: str, value_int: int, value_str: str, ): self.name = name self.value_int = value_int self.value_str = value_str self.ref_syntax = symbol_reference_syntax_for_name(name) self.symbol_reference = SymbolReference( name, reference_restrictions.is_string__all_indirect_refs_are_strings())
def test_symbol_references_with_dir_dependencies(self): # ARRANGE # path_symbol_name = 'PATH_SYMBOL' regex_source_string = (symbol_reference_syntax_for_name(self.STAR_STRING_SYMBOL.name) + symbol_reference_syntax_for_name(path_symbol_name)) expectation = Expectation( references=asrt.matches_sequence([ is_reference_to__regex_string_part(self.STAR_STRING_SYMBOL.name), is_reference_to__regex_string_part(path_symbol_name), ]), validation=ValidationAssertions.post_sds_fails__w_any_msg(), token_stream=assert_token_stream(is_null=asrt.is_true), ) rel_opt_cases = [ RelOptionType.REL_HDS_CASE, RelOptionType.REL_CWD, RelOptionType.REL_ACT, ] for rel_opt in rel_opt_cases: path_symbol = PathDdvSymbolContext.of_no_suffix(path_symbol_name, rel_opt) arrangement = Arrangement( symbols=SymbolContext.symbol_table_of_contexts([ self.STAR_STRING_SYMBOL, path_symbol, ]) ) # ACT & ASSERT # self._check(regex_source_string, arrangement, expectation, )
def test_symbol_references_with_dir_dependencies(self): # ARRANGE # file_ref_symbol_name = 'FILE_REF_SYMBOL' regex_source_string = (symbol_reference_syntax_for_name(self.STAR_STRING_SYMBOL.name) + symbol_reference_syntax_for_name(file_ref_symbol_name)) expectation = Expectation( references=asrt.matches_sequence([ is_reference_to_valid_regex_string_part(self.STAR_STRING_SYMBOL.name), is_reference_to_valid_regex_string_part(file_ref_symbol_name), ]), validation=post_sds_validation_fails(), token_stream=assert_token_stream(is_null=asrt.is_true), ) rel_opt_cases = [ RelOptionType.REL_HOME_CASE, RelOptionType.REL_CWD, RelOptionType.REL_ACT, ] for rel_opt in rel_opt_cases: file_ref_resolver = file_ref_resolvers.of_rel_option(rel_opt) arrangement = Arrangement( symbols=SymbolTable({ self.STAR_STRING_SYMBOL.name: self.STAR_STRING_SYMBOL.value, file_ref_symbol_name: container(file_ref_resolver), }) ) # ACT & ASSERT # self._check(regex_source_string, arrangement, expectation, )
def test_case(self) -> str: one_line_per_predefined_symbol__that_defines_one_symbol_in_terms_of_it = [ args.symbol_def_instruction( builtin_symbol.container.value_type, 'COPY_OF_' + builtin_symbol.name, symbol_reference_syntax_for_name(builtin_symbol.name)).as_str for builtin_symbol in test_case_dir_symbols.ALL ] return lines_content( [phase_header_line(phase_identifier.SETUP)] + one_line_per_predefined_symbol__that_defines_one_symbol_in_terms_of_it )
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 plain_symbol_cases() -> Sequence[NameAndValue[str]]: return [ NameAndValue('empty source', ''), NameAndValue('not a plain symbol name - invalid characters', NOT_A_VALID_SYMBOL_NAME), NameAndValue('not a plain symbol name - quoted - hard', surrounded_by_hard_quotes_str(A_VALID_SYMBOL_NAME)), NameAndValue('not a plain symbol name - quoted - soft', surrounded_by_soft_quotes_str(A_VALID_SYMBOL_NAME)), NameAndValue('not a plain symbol name - symbol reference', symbol_reference_syntax_for_name(A_VALID_SYMBOL_NAME)), NameAndValue( 'not a plain symbol name - broken syntax due to missing end quote', QUOTE_CHAR_FOR_TYPE[QuoteType.SOFT] + A_VALID_SYMBOL_NAME), ]
def test_doc_with_symbol_references(self): content_line_of_here_doc_template = 'content line of here doc with {symbol}' here_doc_contents_template = hd.contents_str_from_lines([content_line_of_here_doc_template]) symbol_name = 'symbol_name' symbol = NameAndValue('symbol_name', 'the symbol value') expected_symbol_references = [ SymbolReference(symbol.name, is_any_data_type()) ] cases = [ ('string value container', data_symbol_utils.string_constant_container('string symbol value')), ('file ref value container', data_symbol_utils.file_ref_constant_container( file_refs.rel_act(file_refs.constant_path_part('file-name.txt')))), ] for case in cases: with self.subTest(case[0]): self._run(assignment_of(' <<MARKER ', [content_line_of_here_doc_template.format( symbol=symbol_reference_syntax_for_name(symbol_name)), 'MARKER', 'following line']), Arrangement( symbols=SymbolTable({ symbol_name: case[1] }) ), Expectation( settings_builder=AssertStdinIsSetToContents( parse_string.string_resolver_from_string( here_doc_contents_template.format( symbol=symbol_reference_syntax_for_name(symbol_name)))), symbol_usages=equals_symbol_references(expected_symbol_references), source=is_at_beginning_of_line(4)), )
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): symbol_name = 'the_symbol_name' space_after = ' ' token_after = str(surrounded_by_hard_quotes('not an expression')) symbol_ref_syntax_cases = [ NameAndValue( 'plain', symbol_name, ), NameAndValue( 'reference syntax', symbol_reference_syntax_for_name(symbol_name), ), ] def cases_for_symbol_syntax( symbol_reference: NameAndValue[str]) -> List[SourceCase]: sf = StringFormatter({ 'symbol_name': symbol_reference.value, 'space_after': space_after, 'token_after': token_after, }) def source(template: str) -> str: return sf.format(template) def name(case: str) -> str: return 'symbol_syntax={} / {}'.format(symbol_reference.name, case) return [ SourceCase(name('first line is only primitive expr'), source('{symbol_name}'), SourceExpectation.is_at_end_of_line(1)), SourceCase( name('first line is primitive expr with space around'), source(' {symbol_name}{space_after}'), SourceExpectation.source_is_not_at_end( current_line_number=1, remaining_part_of_current_line=space_after[1:])), SourceCase( name('expression is followed by non-expression'), source('{symbol_name} {token_after}'), SourceExpectation.source_is_not_at_end( current_line_number=1, remaining_part_of_current_line=token_after)), ]
def _symbol_reference_syntax_table() -> ParagraphItem: return docs.first_column_is_header_table([ [ docs.text_cell('Plain name'), docs.text_cell( syntax_text( syntax_elements.SYMBOL_NAME_SYNTAX_ELEMENT.argument.name)), ], [ docs.text_cell('Special syntax'), docs.text_cell( syntax_text( symbol_reference_syntax_for_name( syntax_elements.SYMBOL_NAME_SYNTAX_ELEMENT.argument. name))), ], ], ' : ')
def runTest(self): # ARRANGE # symbol_in_program_source = NameAndValue('SYMBOL_IN_PROGRAM_SOURCE', data_restrictions_assertions.is__w_str_rendering()) symbol_in_matcher = NameAndValue('SYMBOL_IN_MATCHER', ss_references.IS_STRING_SOURCE_OR_STRING_REFERENCE_RESTRICTION) symbol_in_transformer_of_program = NameAndValue('SYMBOL_IN_TRANSFORMER_OF_PROGRAM', is_reference_restrictions__value_type( [ValueType.STRING_TRANSFORMER])) symbol_in_transformer_of_instruction = NameAndValue('SYMBOL_IN_TRANSFORMER_OF_INSTRUCTION', is_reference_restrictions__value_type( [ValueType.STRING_TRANSFORMER])) program_with_ref_to_symbols = pgm_args.program( pgm_args.interpret_py_source_line( self.configuration.py_source_for_print( symbol_reference_syntax_for_name(symbol_in_program_source.name))), transformation=symbol_in_transformer_of_program.name ) matcher_with_ref_to_symbol = matcher_arguments.equals_matcher(SymbolReferenceArgument(symbol_in_matcher.name)) arguments = po_ab.from_program(program_with_ref_to_symbols, matcher_with_ref_to_symbol, transformation=symbol_in_transformer_of_instruction.name) symbol_usages_assertion = asrt.matches_sequence([ matches_reference(symbol_in_program_source), matches_reference(symbol_in_transformer_of_program), matches_reference(symbol_in_transformer_of_instruction), matches_reference(symbol_in_matcher), ]) source = arguments.as_remaining_source # ACT # actual = self.configuration.parser().parse(ARBITRARY_FS_LOCATION_INFO, source) actual_symbol_usages = actual.symbol_usages() # ASSERT # symbol_usages_assertion.apply_without_message(self, actual_symbol_usages)
def test(self): # ARRANGE # plain_string1 = 'plain_1' plain_string2 = 'plain_2' symbol_name_1 = 'symbol_name_1' symbol_name_2 = 'symbol_name_2' remaining_part_of_current_line_with_sym_ref = ''.join(['before', symbol_reference_syntax_for_name(symbol_name_2), 'after']) cases = [ Case('plain strings', ab.sequence([plain_string1, plain_string2]).as_str, Expectation( elements=[list_resolvers.str_element(plain_string1), list_resolvers.str_element(plain_string2)], validators=asrt.is_empty_sequence, references=asrt.is_empty_sequence, )), Case('symbol reference + plain string + until-end-of-line', ab.sequence([ab.symbol_reference(symbol_name_1), plain_string1, syntax_elements.REMAINING_PART_OF_CURRENT_LINE_AS_LITERAL_MARKER, remaining_part_of_current_line_with_sym_ref, ]).as_str, Expectation( elements=[list_resolvers.symbol_element(symbol_reference(symbol_name_1)), list_resolvers.str_element(plain_string1), list_resolvers.string_element(string_resolvers.from_fragments([ string_resolvers.str_fragment('before'), string_resolvers.symbol_fragment(symbol_reference(symbol_name_2)), string_resolvers.str_fragment('after'), ])) ], validators=asrt.is_empty_sequence, references=asrt.matches_sequence([ asrt_sym_ref.matches_reference_2(symbol_name_1, is_any_data_type_reference_restrictions()), asrt_sym_ref.matches_reference_2(symbol_name_2, is_any_data_type_reference_restrictions()), ]), )), ] # ACT & ASSERT # _test_cases(self, cases)
def test_remaining_part_of_current_line_as_literal(self): # ARRANGE # symbol_name = 'symbol_name' str_with_space_and_invalid_token_syntax = 'before and after space, ' + SOFT_QUOTE_CHAR + 'after quote' cases = [ Case('string with one space after marker, and no space at EOL', ' '.join([ syntax_elements.REMAINING_PART_OF_CURRENT_LINE_AS_LITERAL_MARKER, str_with_space_and_invalid_token_syntax]), Expectation( elements=[list_resolvers.str_element(str_with_space_and_invalid_token_syntax)], validators=asrt.is_empty_sequence, references=asrt.is_empty_sequence, )), Case('with surrounding space', ' '.join([ syntax_elements.REMAINING_PART_OF_CURRENT_LINE_AS_LITERAL_MARKER, ' ' + str_with_space_and_invalid_token_syntax + ' \t ']), Expectation( elements=[list_resolvers.str_element(str_with_space_and_invalid_token_syntax)], validators=asrt.is_empty_sequence, references=asrt.is_empty_sequence, )), Case('with symbol reference', ' '.join([ syntax_elements.REMAINING_PART_OF_CURRENT_LINE_AS_LITERAL_MARKER, ''.join(['before', symbol_reference_syntax_for_name(symbol_name), 'after'])]), Expectation( elements=[list_resolvers.string_element(string_resolvers.from_fragments([ string_resolvers.str_fragment('before'), string_resolvers.symbol_fragment(symbol_reference(symbol_name)), string_resolvers.str_fragment('after'), ])) ], validators=asrt.is_empty_sequence, references=asrt.matches_sequence([asrt_sym_ref.matches_reference_2( symbol_name, is_any_data_type_reference_restrictions()) ]), )), ] # ACT & ASSERT # _test_cases(self, cases)
def test_token_SHOULD_be_interpreted_as_sym_ref_WHEN_sym_ref_syntax_is_used_for_existing_primitive( self): for grammar_description, grammar in GRAMMARS: with self.subTest(grammar=grammar_description): parse_check.check( self, self.parser_maker, Arrangement( grammar=grammar, source=remaining_source( symbol_reference_syntax_for_name( ast.PRIMITIVE_SANS_ARG)), ), Expectation( expression=ast.RefExpr(ast.PRIMITIVE_SANS_ARG), source=asrt_source.is_at_end_of_line(1), ), )