def test_valid_syntax_without_symbol_references(self): single_string_token_value = 'singleStringTokenValue' multiple_tokens_string_value = 'multiple tokens string value' multi_line_string = 'string\nspanning multiple \n lines\n' cases = [ Variant( 'non-quoted string-token on single line', StringLiteralAbsStx(single_string_token_value), single_string_token_value, ), Variant( 'quoted string-token on single line', StringLiteralAbsStx(multiple_tokens_string_value, QuoteType.SOFT), multiple_tokens_string_value, ), Variant( 'quoted multi line string', StringLiteralAbsStx(multi_line_string, QuoteType.SOFT), multi_line_string, ), ] for variant in cases: # ACT & ASSERT # CHECKER.check(self, equivalent_source_variants__for_expr_parse__s__nsc, variant.syntax, Arrangement(), Expectation( [], variant.resolved_str, ))
def test_regular_file(self): file_name = 'destination.txt' file_name_syntax = StringLiteralAbsStx(file_name, QuoteType.HARD) explicit_file_contents = str_src_abs_stx.StringSourceOfStringAbsStx.of_plain( StringLiteralAbsStx.empty_string() ) file_spec_syntax = regular_file_spec( file_name_syntax, FileContentsExplicitAbsStx(ModificationType.APPEND, explicit_file_contents), ) for dir_contents_case in file_must_exist_as_regular(file_name): with self.subTest(dir_contents=dir_contents_case.name): integration_check.CHECKER.check__abs_stx( self, LiteralFilesSourceAbsStx([file_spec_syntax]), dir_contents_case.value, arrangement_w_tcds(), Expectation( parse=IS_AT_END_OF_1ST_LNE, execution=ExecutionExpectation( is_hard_error=asrt_text_doc.is_any_text(), ) ), )
def file_must_exist_as_regular_source_cases(file_name: str) -> Sequence[NameAndValue[FileSpecAbsStx]]: file_name_syntax = StringLiteralAbsStx(file_name, QuoteType.HARD) explicit_file_contents = str_src_abs_stx.StringSourceOfStringAbsStx.of_plain( StringLiteralAbsStx.empty_string() ) explicit_dir_contents = LiteralFilesSourceAbsStx(()) return [ NameAndValue( 'regular / explicit append', regular_file_spec(file_name_syntax, FileContentsExplicitAbsStx(ModificationType.CREATE, explicit_file_contents)), ), NameAndValue( 'dir / implicit empty', dir_spec(file_name_syntax, DirContentsEmptyAbsStx()), ), NameAndValue( 'dir / explicit creation', dir_spec(file_name_syntax, DirContentsExplicitAbsStx(ModificationType.CREATE, explicit_dir_contents)), ), ]
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_superfluous_arguments_after_explicit_list_delimiter(self): stop_element = ListElementStringAbsStx( StringLiteralAbsStx(defs.STOP_AT_CHAR)) invalid_list = NonEmptyListAbsStx([ stop_element, ListElementStringAbsStx(StringLiteralAbsStx('valid')), ]) PARSE_CHECKER.check_invalid_syntax__abs_stx( self, invalid_list, )
def of_str(regex_token: str, replacement_token: str, preserve_new_lines: bool, lines_filter: Optional[LineMatcherAbsStx], ) -> 'ReplaceRegexAbsStx': return ReplaceRegexAbsStx( StringLiteralAbsStx(regex_token), StringLiteralAbsStx(replacement_token), preserve_new_lines, lines_filter, )
def test_valid_syntax_with_symbol_references(self): symbol = StringConstantSymbolContext('symbol_name', 'symbol value') before_symbol = 'text before symbol' after_symbol = 'text after symbol' cases = [ Variant( 'single unquoted symbol reference', symbol.abstract_syntax, symbol.str_value, ), Variant( 'reference embedded in quoted string', StringLiteralAbsStx( '{before_sym_ref}{sym_ref}{after_sym_ref}'.format( sym_ref=symbol.name__sym_ref_syntax, before_sym_ref=before_symbol, after_sym_ref=after_symbol, ), QuoteType.SOFT, ), before_symbol + symbol.str_value + after_symbol, ), ] for variant in cases: # ACT & ASSERT # CHECKER.check( self, equivalent_source_variants__for_expr_parse__s__nsc, variant.syntax, Arrangement(symbol.symbol_table), Expectation( [symbol.reference__w_str_rendering], variant.resolved_str, ))
def of_str( var_name: str, phase_spec: Optional[Phase], quoting: Optional[QuoteType] = None, ) -> 'UnsetVariableArgumentsAbsStx': return UnsetVariableArgumentsAbsStx( StringLiteralAbsStx(var_name, quoting), phase_spec)
def runTest(self): # ARRANGE # symbol_in_regex = StringConstantSymbolContext( 'symbol_in_regex', 'plain string pattern', default_restrictions=asrt_regex.is_reference_restrictions__regex()) symbol_in_replacement = StringConstantSymbolContext( 'symbol_in_replacement', 'the replacement', default_restrictions=asrt_ref_rest.is__w_str_rendering(), ) input_lines = [ symbol_in_regex.str_value, ] expected_lines = [ symbol_in_replacement.str_value, ] quoting_cases = [ None, QuoteType.SOFT, ] for line_filter_case in LINE_FILTER_CASES: all_symbols = line_filter_case.value.symbols + [ symbol_in_regex, symbol_in_replacement, ] for preserve_new_lines in [False, True]: for quoting_variant in quoting_cases: source = ReplaceRegexAbsStx( StringLiteralAbsStx( symbol_in_regex.name__sym_ref_syntax, quoting_variant), symbol_in_replacement.abstract_syntax, preserve_new_lines=preserve_new_lines, lines_filter=line_filter_case.value.syntax, ) # ACT & ASSERT # integration_check.CHECKER__PARSE_FULL.check__abs_stx__layout__std_source_variants( self, source, model_constructor.of_lines(self, input_lines), arrangement_w_tcds( symbols=SymbolContext.symbol_table_of_contexts( all_symbols), ), expectation_of_successful_replace_execution__multi( symbol_references=SymbolContext. references_assertion_of_contexts(all_symbols), may_depend_on_external_resources=line_filter_case. value.may_depend_on_external_resources, output_lines=expected_lines, ), sub_test_identifiers={ 'preserve_new_lines': preserve_new_lines, 'quoting': quoting_variant, 'line_filtering': line_filter_case.name, })
def of_cmp_op__str( operator: ComparisonOperator, operand: str, quoting: Optional[QuoteType] = None, ) -> 'IntegerMatcherComparisonAbsStx': return IntegerMatcherComparisonAbsStx.of_cmp_op( operator, StringLiteralAbsStx(operand, quoting), )
def of_str( var_name: str, value: str, phase_spec: Optional[Phase], quoting: Optional[QuoteType] = None, ) -> 'SetVariableArgumentsAbsStx': return SetVariableArgumentsAbsStx( StringLiteralAbsStx(var_name), StringSourceOfStringAbsStx.of_str(value, quoting), phase_spec)
def test_removal_of_new_lines_SHOULD_join_lines(self): # ARRANGE # cases = [ NIE('final line not ended by new-line', input_value=[ '1\n', '2\n', '3', ], expected_value=[ '123', ]), NIE('final line ended by new-line', input_value=[ '1\n', '2\n', '3\n', ], expected_value=[ '123', ]), ] for line_filter_case in LINE_FILTER_CASES: for case in cases: with self.subTest(model=case.name, line_filtering=line_filter_case.name): nl_string_symbol = StringConstantSymbolContext( 'NL', '\n', default_restrictions=asrt_regex. is_reference_restrictions__regex(), ) all_symbols = line_filter_case.value.symbols + [ nl_string_symbol ] source = ReplaceRegexAbsStx( nl_string_symbol.abstract_syntax, StringLiteralAbsStx.empty_string(), preserve_new_lines=False, lines_filter=line_filter_case.value.syntax, ) # ACT & ASSERT # integration_check.CHECKER__PARSE_SIMPLE.check__abs_stx( self, source, model_constructor.of_lines(self, case.input_value), arrangement_w_tcds( symbols=SymbolContext.symbol_table_of_contexts( all_symbols), ), expectation_of_successful_replace_execution( symbol_references=SymbolContext. references_assertion_of_contexts(all_symbols), may_depend_on_external_resources=line_filter_case. value.may_depend_on_external_resources, output_lines=case.expected_value, ))
def test_illegal_path_with_regular_file_as_dir_component(self): # ARRANGE # existing_regular_file = fs.File.empty('regular-file') file_name = str(PurePosixPath(existing_regular_file.name, 'destination')) file_name_syntax = StringLiteralAbsStx(file_name, QuoteType.HARD) explicit_file_contents = str_src_abs_stx.StringSourceOfStringAbsStx.of_plain( StringLiteralAbsStx.empty_string() ) file_spec_cases = [ NameAndValue( 'regular', regular_file_spec( file_name_syntax, FileContentsExplicitAbsStx(ModificationType.APPEND, explicit_file_contents), ), ), NameAndValue( 'dir', dir_spec( file_name_syntax, DirContentsExplicitAbsStx(ModificationType.APPEND, LiteralFilesSourceAbsStx(())), ), ), ] for file_spec_case in file_spec_cases: with self.subTest(file_spec=file_spec_case.name): # ACT & ASSERT # integration_check.CHECKER.check__abs_stx( self, LiteralFilesSourceAbsStx([file_spec_case.value]), [existing_regular_file], arrangement_w_tcds(), Expectation( parse=IS_AT_END_OF_1ST_LNE, execution=ExecutionExpectation( is_hard_error=asrt_text_doc.is_any_text(), ) ), )
def runTest(self): # ARRANGE # for value_case in INVALID_INT_VALUES: with self.subTest(value_case): # ACT & ASSERT # self.conf.instruction_checker.check_parsing__abs_stx__const( self, self.conf.parser(), InstructionArgumentsAbsStx.of_int( StringLiteralAbsStx(value_case)), self.conf.arrangement(), self.conf.expect_failing_validation_pre_sds())
def runTest(self): # ACT & ASSERT # name = StringLiteralAbsStx('name') def expectation_corresponding_to( case: str_src_validation_cases.ValidationCase): return (self.conf.expect_failing_validation_pre_sds( case.assertion.pre_sds, symbol_usages=case.symbol_context.usages_assertion) if not case.expectation.passes_pre_sds else self.conf.expect_hard_error_of_main__any( symbol_usages=case.symbol_context.usages_assertion))
def shell() -> PgmAndArgsCase: shell_command_line = 'the shell command line' return PgmAndArgsCase.wo_tcds( 'shell', pgm_and_args=pgm_abs_stx.ProgramOfShellCommandLineAbsStx( StringLiteralAbsStx(shell_command_line) ), expected_command_driver=prim_asrt__constant( asrt_command.matches_shell_command_driver(asrt.equals(shell_command_line)) ) )
def runTest(self): # ARRANGE # missing_contents_file_spec = abs_stx.FileSpecAbsStx( 'invalid_file_type_token', StringLiteralAbsStx('valid_file_name'), abs_stx.FileContentsEmptyAbsStx()) literal_syntax = abs_stx.LiteralFilesSourceAbsStx( [missing_contents_file_spec]) # ACT & ASSERT # integration_check.PARSE_CHECKER__FULL.check_invalid_syntax__abs_stx( self, literal_syntax, )
def runTest(self): for value_case in INVALID_INT_VALUES: CHECKER.check__abs_stx__layout_and_source_variants( self, InstructionArgumentsAbsStx.of_int( StringLiteralAbsStx(value_case)), Arrangement.phase_agnostic(), MultiSourceExpectation.phase_agnostic( validation=ValidationAssertions.pre_sds_fails__w_any_msg( )), sub_test_identifiers={'value_case': value_case}, )
def runTest(self): # ARRANGE # for phase_spec in PHASE_SPECS: cases = [ NameAndValue( 'missing arguments', SetVariableArgumentsAbsStx( StringLiteralAbsStx(''), StringSourceOfStringAbsStx.of_str(''), phase_spec=phase_spec, ), ), NameAndValue( 'more than three arguments', SetVariableArgumentsAbsStx( StringLiteralAbsStx('arg1'), StringSourceOfStringAbsStx.of_str('arg2 arg3'), phase_spec=phase_spec, ), ), NameAndValue( 'invalid quoting of value', SetVariableArgumentsAbsStx( StringLiteralAbsStx('name'), StringSourceOfStringAbsStx(MISSING_END_QUOTE__SOFT), phase_spec=phase_spec, ), ), ] for case in cases: # ACT & ASSERT # PARSE_CHECKER.check_invalid_syntax__abs_stx( self, case.value, { 'phase_spec': phase_spec, 'variant': case.name, }, )
def test_shell_program(self): argument_string_template = 'first {string_symbol} between {list_symbol} after' string_argument_symbol = StringConstantSymbolContext( 'STRING_ARGUMENT_SYMBOL', 'string argument', ) list_argument_symbol = ListConstantSymbolContext( 'LIST_ARGUMENT_SYMBOL', ['list_arg_value_1', 'list arg value 2']) symbols = [string_argument_symbol, list_argument_symbol] command_line_syntax_str = argument_string_template.format( string_symbol=string_argument_symbol.name__sym_ref_syntax, list_symbol=list_argument_symbol.name__sym_ref_syntax, ) command_line_str = argument_string_template.format( string_symbol=string_argument_symbol.str_value, list_symbol=' '.join(list_argument_symbol.constant_list), ) syntax = ProgramOfShellCommandLineAbsStx( StringLiteralAbsStx(command_line_syntax_str)) def expected_program( env: AssertionResolvingEnvironment) -> Assertion[Program]: return asrt_pgm_val.matches_program( command=asrt_command.equals_shell_command( command_line=command_line_str, arguments=[], ), stdin=asrt_pgm_val.is_no_stdin(), transformer=asrt_pgm_val.is_no_transformation(), ) expectation = MultiSourceExpectation( symbol_references=asrt.matches_sequence([ string_argument_symbol.reference_assertion__w_str_rendering, list_argument_symbol.reference_assertion__w_str_rendering, ]), primitive=expected_program, ) # ACT & ASSERT # CHECKER_WO_EXECUTION.check__abs_stx__layouts__source_variants__wo_input( self, equivalent_source_variants__for_consume_until_end_of_last_line__s__nsc, syntax, arrangement_wo_tcds( symbols=SymbolContext.symbol_table_of_contexts(symbols), ), expectation, )
def runTest(self): # ARRANGE # for phase_spec in PHASE_SPECS: cases = [ NameAndValue( 'invalid quoting', UnsetVariableArgumentsAbsStx.of_str( MISSING_END_QUOTE_STR__HARD, phase_spec=phase_spec), ), NameAndValue( 'missing arguments', UnsetVariableArgumentsAbsStx(StringLiteralAbsStx(''), phase_spec=phase_spec), ), NameAndValue( 'more than one argument', SequenceAbsStx.followed_by_superfluous( UnsetVariableArgumentsAbsStx( StringLiteralAbsStx('name'), phase_spec=phase_spec))), NameAndValue( 'unset identifier must not be quoted', SequenceAbsStx([ StringLiteralAbsStx(defs.UNSET_IDENTIFIER, QuoteType.HARD), StringLiteralAbsStx('var_name'), ])), ] for case in cases: # ACT & ASSERT # PARSE_CHECKER.check_invalid_syntax__abs_stx( self, case.value, { 'phase_spec': phase_spec, 'variant': case.name, }, )
def test_regular_file(self): valid_file_name = StringLiteralAbsStx('valid_file_name') for validation_case in str_src_validation_cases.failing_validation_cases(): symbol_context = validation_case.value.symbol_context for contents_case in ContentsCase.cases(): invalid_file_spec = abs_stx.regular_file_spec( valid_file_name, abs_stx.FileContentsExplicitAbsStx(contents_case.modification_type, symbol_context.abstract_syntax), ) # ACT & ASSERT # self._check_case( invalid_file_spec, contents_case, validation_case, )
def _list_case(contents_transformation: Callable[[str], str]) -> Case: elements = ['1st element', '2nd element'] def get_assertion_on_primitive( env: AssertionResolvingEnvironment) -> Assertion[StringSource]: list_as_str = list_formatting.format_elements(elements) return asrt_string_source.pre_post_freeze__matches_str__const( contents_transformation(list_as_str), may_depend_on_external_resources=False) symbol_context = ListSymbolContext.of_constants('LIST_SYMBOL', elements) return Case( StringSourceOfStringAbsStx.of_plain( StringLiteralAbsStx(symbol_context.name__sym_ref_syntax, QuoteType.SOFT)), symbol_context, get_assertion_on_primitive, )
def cases__w_argument_list__excluding_program_reference() -> List[PgmAndArgsCase]: """Cases of pgm-and-arg:s that have a list of arguments.""" executable_file = fs.executable_file('executable-file', '') exe_file_relativity = rel_opt.conf_rel_hds(RelHdsOptionType.REL_HDS_CASE) executable_file_ddv = path_ddvs.of_rel_option(exe_file_relativity.relativity, path_ddvs.constant_path_part(executable_file.name) ) system_program = 'the-system-program' return [ PgmAndArgsCase.w_tcds( 'executable file', pgm_and_args=pgm_abs_stx.ProgramOfExecutableFileCommandLineAbsStx( exe_file_relativity.named_file_conf(executable_file.name).abstract_syntax ), expected_command_driver=lambda env: ( asrt_command.matches_executable_file_command_driver( asrt.equals(executable_file_ddv.value_of_any_dependency__d(env.tcds).primitive), )), tcds=exe_file_relativity.populator_for_relativity_option_root__hds( DirContents([executable_file]) ) ), PgmAndArgsCase.wo_tcds( '-python', pgm_and_args=pgm_abs_stx.ProgramOfPythonInterpreterAbsStx(()), expected_command_driver=prim_asrt__constant( asrt_command.matches_executable_file_command_driver( asrt_path.path_as_str(asrt.equals(sys.executable)), )), ), PgmAndArgsCase.wo_tcds( 'system program', pgm_and_args=pgm_abs_stx.ProgramOfSystemCommandLineAbsStx( StringLiteralAbsStx(system_program) ), expected_command_driver=prim_asrt__constant( asrt_command.matches_system_program_command_driver( asrt.equals(system_program) )) ), ]
def runTest(self): # ARRANGE # src_dir_name = 'source-dir' path_symbol = StringReferenceAbsStx('SRC_PATH_SYMBOL') dst_path_abs_stx = PathStringAbsStx.of_components([ path_symbol, StringLiteralAbsStx(src_dir_name), ]) arguments_syntax = abs_stx.CopyOfDirContentsAbsStx(dst_path_abs_stx) execution_cases = validation_exe_cases(src_dir_name, path_symbol.name) # ACT & ASSERT # integration_check.CHECKER.check_abs_stx__multi__w_source_variants( self, arguments_syntax, symbol_references=asrt.matches_singleton_sequence( is_src_dir_argument(path_symbol.name) ), input_=models.arbitrary(), execution=execution_cases, )
def test_literal(self): # ARRANGE # defined_name = symbol_syntax.A_VALID_SYMBOL_NAME create_file = fs.File('created-file.txt', 'contents of created file') literal_syntax = abs_stx.LiteralFilesSourceAbsStx([ abs_stx.regular_file_spec( StringLiteralAbsStx(create_file.name, QuoteType.HARD), abs_stx.FileContentsExplicitAbsStx( ModificationType.CREATE, StringSourceOfStringAbsStx.of_str(create_file.contents, QuoteType.HARD), ) ) ]) syntax = _syntax_of( literal_syntax, defined_name, ) arrangement = Arrangement.phase_agnostic() # EXPECTATION # expectation = _expect_definition_of( defined_name, SymbolTable.empty(), (), asrt.is_empty_sequence, asrt_fs.dir_contains_exactly_2([create_file]) ) # ACT & ASSERT # INSTRUCTION_CHECKER.check__abs_stx__std_layouts_and_source_variants( self, syntax, arrangement, expectation, )
def runTest(self): # ARRANGE # for modification_type in abs_stx.ModificationType: for file_type in abs_stx.FileType: missing_contents_file_spec = abs_stx.FileSpecAbsStx.of_file_type( file_type, StringLiteralAbsStx('valid_file_name'), abs_stx.CustomContentsAbsStx( abs_stx.ContentsAbsStx.of_modification_type( modification_type, CustomAbsStx.empty(), ), )) literal_syntax = abs_stx.LiteralFilesSourceAbsStx( [missing_contents_file_spec]) # ACT & ASSERT # integration_check.PARSE_CHECKER__FULL.check_invalid_syntax__abs_stx( self, literal_syntax, sub_test_identifiers={ 'modification_type': modification_type, 'file_type': file_type, })
def test_string_literal(self): for other_valid_file_spec_case in OTHER_VALID_FILE_SPECS: for file_name_case in INVALID_FILE_NAMES: file_name_abs_stx = StringLiteralAbsStx(file_name_case.value, QuoteType.HARD) for file_spec_case in file_type_and_contents_variants(file_name_abs_stx): integration_check.CHECKER.check__abs_stx__layout__std_source_variants( self, LiteralFilesSourceAbsStx(other_valid_file_spec_case.value + [file_spec_case.value]), models.empty(), arrangement_wo_tcds(), MultiSourceExpectation( execution=ExecutionExpectation( validation=ValidationAssertions.pre_sds_fails__w_any_msg() ) ), sub_test_identifiers={ 'file-name': file_name_case.name, 'type-and-contents': file_spec_case.name, 'other-valid-file-spec': other_valid_file_spec_case.name, } )
def runTest(self): # ARRANGE # invalid_modification_types = [':', 2 * syntax.EXPLICIT_CREATE, 'text'] for invalid_modification_type in invalid_modification_types: for file_type in abs_stx.FileType: missing_contents_file_spec = abs_stx.FileSpecAbsStx.of_file_type( file_type, StringLiteralAbsStx('valid_file_name'), abs_stx.CustomContentsAbsStx( abs_stx.ContentsAbsStx.of_modification( TokenSequence.singleton(invalid_modification_type), CustomAbsStx.singleton(A_VALID_SYMBOL_NAME), ), )) literal_syntax = abs_stx.LiteralFilesSourceAbsStx( [missing_contents_file_spec]) # ACT & ASSERT # integration_check.PARSE_CHECKER__FULL.check_invalid_syntax__abs_stx( self, literal_syntax, sub_test_identifiers={ 'file_type': file_type, 'invalid_modification_type': invalid_modification_type, })
def test_set_value_that_references_an_env_var_in_string_ref_value(self): # ARRANGE # existing_env_var = NameAndValue('MY_VAR', 'MY_VAL') defined_env_var = NameAndValue('name', existing_env_var.value) source_string_symbol_w_env_var_ref = StringSourceSymbolContext.of_primitive_constant( 'SYMBOL_W_ENV_VAR_REF', env_var_ref_syntax(existing_env_var.name)) environ__before = { existing_env_var.name: existing_env_var.value, } environ__after = { defined_env_var.name: defined_env_var.value, existing_env_var.name: existing_env_var.value, } # ACT & ASSERT # CHECKER.check__abs_stx__std_layouts_and_source_variants( self, SetVariableArgumentsAbsStx( StringLiteralAbsStx(defined_env_var.name), source_string_symbol_w_env_var_ref.abstract_syntax, phase_spec=None), arrangement=Arrangement.setup_phase_aware( symbols=source_string_symbol_w_env_var_ref.symbol_table, process_execution_settings=ProcessExecutionSettings. with_environ(environ__before), ), expectation=MultiSourceExpectation.setup_phase_aware( symbol_usages=source_string_symbol_w_env_var_ref. references_assertion, main_side_effect_on_environment_variables=asrt.equals( environ__after), ))