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_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_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 parse_from_source(self, source: ParseSource) -> SetupPhaseInstruction: args = source.remaining_part_of_current_line source.consume_current_line() components = args.split() if len(components) != self.num_args: raise ValueError('Expecting {} args. Found {} args'.format(self.num_args, len(components))) return self._parse(components)
def _advance_source(source: ParseSource): if source.has_current_line: if not source.is_at_eol__except_for_space: source.consume(len(source.remaining_part_of_current_line)) misc_utils.raise_superfluous_arguments( source.remaining_part_of_current_line.strip()) source.consume_current_line()
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> ParsedInstruction: current_line = source.current_line source.consume_current_line() instruction = ActPhaseInstructionThatRecords( fs_location_info.current_source_file, current_line.text) return ParsedInstruction(line_sequence_from_line(current_line), InstructionInfo(instruction, None))
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_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 parse_from_parse_source(source: ParseSource, conf: RelOptionArgumentConfiguration = CONFIGURATION) -> StringOrFileRefResolver: with from_parse_source(source, consume_last_line_if_is_at_eol_after_parse=False) as token_parser: ret_val = parse_from_token_parser(token_parser, conf) if ret_val.source_type is SourceType.HERE_DOC: if source.is_at_eol: source.consume_current_line() return ret_val
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> ParsedInstruction: current_line = source.current_line source.consume_current_line() instruction = ActPhaseInstructionThatRecords(fs_location_info.current_source_file, current_line.text) return ParsedInstruction(line_sequence_from_line(current_line), InstructionInfo(instruction, None))
def _syntax_error_if_not_at_eof(source: parse_source.ParseSource): if source.is_at_eof: return if source.is_at_eol__except_for_space: source.consume_current_line() _syntax_error_if_not_at_eof(source) else: raise ParseException.of_str( 'Superfluous arguments of {PROGRAM}: {src}'.format( PROGRAM=syntax_elements.PROGRAM_SYNTAX_ELEMENT.singular_name, src=source.remaining_part_of_current_line))
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 _consume_and_return_current_line(source: ParseSource, line_predicate_for_line_to_consume: Callable[[str], bool], ) -> line_source.LineSequence: current_line = source.current_line lines = [current_line.text] source.consume_current_line() while source.has_current_line and line_predicate_for_line_to_consume(source.current_line_text): lines.append(source.current_line_text) source.consume_current_line() return line_source.LineSequence(current_line.line_number, tuple(lines))
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> sut.ParsedInstruction: first_line_number = source.current_line_number dummy_source = line_source.LineSequence(first_line_number, (source.current_line_text,)) is_instruction = False while not source.is_at_eof and source.current_line_text.startswith(self.instruction_line_identifier): source.consume_current_line() is_instruction = True if not is_instruction: raise ValueError('Not an instruction') return sut.ParsedInstruction(dummy_source, InstructionInfo(Instruction(), None))
def _consume_and_return_current_line( source: ParseSource, line_predicate_for_line_to_consume: Callable[[str], bool], ) -> line_source.LineSequence: current_line = source.current_line lines = [current_line.text] source.consume_current_line() while source.has_current_line and line_predicate_for_line_to_consume( source.current_line_text): lines.append(source.current_line_text) source.consume_current_line() return line_source.LineSequence(current_line.line_number, tuple(lines))
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> sut.ParsedInstruction: first_line_number = source.current_line_number dummy_source = line_source.LineSequence(first_line_number, (source.current_line_text, )) is_instruction = False while not source.is_at_eof and source.current_line_text.startswith( self.instruction_line_identifier): source.consume_current_line() is_instruction = True if not is_instruction: raise ValueError('Not an instruction') return sut.ParsedInstruction(dummy_source, InstructionInfo(Instruction(), None))
def from_parse_source(source: ParseSource, consume_last_line_if_is_at_eol_after_parse: bool = False, consume_last_line_if_is_at_eof_after_parse: bool = False): """ Gives a :class:`TokenParserPrime` backed by the given :class:`ParseSource`. The source of the :class:`TokenParserPrime` is the remaining sources of the :class:`ParseSource` """ tp = new_token_parser(source.remaining_source, first_line_number=source.current_line_number) yield tp source.consume(tp.token_stream.position) if consume_last_line_if_is_at_eol_after_parse and source.is_at_eol: source.consume_current_line() elif consume_last_line_if_is_at_eof_after_parse and source.is_at_eof: source.consume_current_line()
def _consume_space_and_comment_lines(source: ParseSource, first_line: Line): error_message = 'End-of-file reached without finding an instruction (following a description)' if source.is_at_eof: raise new_unrecognized_section_element_error_of_single_line(first_line, error_message) line_in_error_message = first_line source.consume_initial_space_on_current_line() if not source.is_at_eol: return source.consume_current_line() while not source.is_at_eof: if syntax.is_empty_or_comment_line(source.current_line_text): line_in_error_message = source.current_line source.consume_current_line() else: source.consume_initial_space_on_current_line() return raise new_unrecognized_section_element_error_of_single_line(line_in_error_message, error_message)
def _consume_instruction_source(source: ParseSource) -> line_source.LineSequence: current_line = source.current_line_text if is_multi_line_instruction_line(current_line): first_line_number = source.current_line_number lines = [current_line] source.consume_current_line() # Eat additional lines while source.has_current_line: current_line = source.current_line_text if is_multi_line_instruction_line(current_line): lines.append(current_line) source.consume_current_line() else: break return line_source.LineSequence(first_line_number, tuple(lines)) else: return consume_current_line_and_return_it_as_line_sequence(source)
def _consume_instruction_source( source: ParseSource) -> line_source.LineSequence: current_line = source.current_line_text if is_multi_line_instruction_line(current_line): first_line_number = source.current_line_number lines = [current_line] source.consume_current_line() # Eat additional lines while source.has_current_line: current_line = source.current_line_text if is_multi_line_instruction_line(current_line): lines.append(current_line) source.consume_current_line() else: break return line_source.LineSequence(first_line_number, tuple(lines)) else: return consume_current_line_and_return_it_as_line_sequence(source)
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> ConfigurationPhaseInstruction: rest_of_line = source.remaining_part_of_current_line source.consume_current_line() argument = extract_single_eq_argument_string(_DIR_ARG.name, rest_of_line) path_arguments = split_arguments_list_string(argument) if len(path_arguments) > 1: raise SingleInstructionInvalidArgumentException('Too many arguments: ' + argument) try: path_argument = pathlib.Path(pathlib.PurePosixPath(path_arguments[0])) except ValueError as ex: raise SingleInstructionInvalidArgumentException('Invalid path syntax:\n' + str(ex)) return _Instruction(self.dir_to_set, fs_location_info.current_source_file.abs_path_of_dir_containing_last_file_base_name, path_argument)
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> ParsedInstruction: first_line_number = source.current_line_number current_line = source.current_line_text lines_read = [_un_escape(current_line)] source.consume_current_line() while not source.is_at_eof: current_line = source.current_line_text if syntax.is_section_header_line(current_line): break else: lines_read.append(_un_escape(current_line)) source.consume_current_line() line_sequence = LineSequence(first_line_number, tuple(lines_read)) return ParsedInstruction( line_sequence, InstructionInfo(SourceCodeInstruction(line_sequence), None))
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> Optional[ParsedFileInclusionDirective]: parts = source.current_line_text.strip().split() if len(parts) == 0 or parts[0] != self._directive_token: return None directive_source = line_sequence_from_line(source.current_line) source.consume_current_line() if len(parts) == 1: raise RecognizedSectionElementSourceError(directive_source, 'Missing {} argument'.format(FILE_ARGUMENT_NAME)) if len(parts) != 2: raise RecognizedSectionElementSourceError(directive_source, 'Superfluous arguments: ' + ' '.join(parts[2:])) path = pathlib.Path(pathlib.PurePosixPath(parts[1])) return ParsedFileInclusionDirective(directive_source, [path])
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> ParsedInstruction: first_line_number = source.current_line_number current_line = source.current_line_text lines_read = [_un_escape(current_line)] source.consume_current_line() while not source.is_at_eof: current_line = source.current_line_text if syntax.is_section_header_line(current_line): break else: lines_read.append(_un_escape(current_line)) source.consume_current_line() line_sequence = LineSequence(first_line_number, tuple(lines_read)) return ParsedInstruction(line_sequence, InstructionInfo(SourceCodeInstruction(line_sequence), None))
def from_parse_source( source: ParseSource, consume_last_line_if_is_at_eol_after_parse: bool = False, consume_last_line_if_is_at_eof_after_parse: bool = False ) -> ContextManager[TokenParser]: """ Gives a :class:`TokenParser` backed by the given :class:`ParseSource`. The source of the :class:`TokenParser` is the remaining sources of the :class:`ParseSource` """ tp = new_token_parser(source.remaining_source, first_line_number=source.current_line_number) try: yield tp finally: source.consume(tp.token_stream.position) if consume_last_line_if_is_at_eol_after_parse and source.is_at_eol__except_for_space: source.consume_current_line() elif consume_last_line_if_is_at_eof_after_parse and source.is_at_eof: source.consume_current_line()
def _consume_space_and_comment_lines(source: ParseSource, first_line: Line): if source.is_at_eof: raise new_unrecognized_section_element_error_of_single_line( first_line, _ERR_MSG__MISSING_INSTRUCTION_AFTER_DESCRIPTION, ) line_in_error_message = first_line source.consume_initial_space_on_current_line() if not source.is_at_eol: return source.consume_current_line() while not source.is_at_eof: if syntax.is_empty_or_comment_line(source.current_line_text): line_in_error_message = source.current_line source.consume_current_line() else: source.consume_initial_space_on_current_line() return raise new_unrecognized_section_element_error_of_single_line( line_in_error_message, _ERR_MSG__MISSING_INSTRUCTION_AFTER_DESCRIPTION)
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> model.Instruction: source.consume_current_line() return SetupPhaseInstructionThatAssertsEnvVars(self.put, self.expected_to_exist)
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> embryo.InstructionEmbryo[T]: ret_val = self.parser_that_do_not_consume_any_source.parse(fs_location_info, source) source.consume_current_line() return ret_val
def consume_current_line_and_return_it_as_line_sequence(source: ParseSource) -> line_source.LineSequence: ret_val = line_source.LineSequence(source.current_line_number, (source.current_line_text,)) source.consume_current_line() return ret_val
def parse_from_source(self, source: ParseSource) -> model.Instruction: ret_val = Instruction(source.current_line_number, source.remaining_part_of_current_line) source.consume_current_line() return ret_val
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> InstructionEmbryo: rest_of_line = source.remaining_part_of_current_line source.consume_current_line() return self._parse(rest_of_line)
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> ParsedSectionElement: source.consume_current_line() return self.return_value
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> model.Instruction: source.consume_current_line() return SetupPhaseInstructionThatAssertsEnvVars( self.put, self.expected_default, self.expected_from_defaults_getter)
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> model.Instruction: str_to_record = source.remaining_part_of_current_line source.consume_current_line() return self.mk_instruction(StringRecorder(self.recorder, fs_location_info, str_to_record))
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> model.Instruction: source.consume_current_line() return ConfigPhaseInstructionThatAssertsHdsDirs( self.put, self.assertion)
def parse_from_source(self, source: ParseSource) -> Instruction: source.consume_current_line() return self.instruction
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> model.Instruction: source.consume_current_line() self._assert_root_source_file_location_corresponds_to(fs_location_info) return configuration_phase_instruction_that()
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> model.Instruction: rest_of_line = source.remaining_part_of_current_line source.consume_current_line() return self._parse(rest_of_line)