Пример #1
0
    def test_only_lines_matching_line_matcher_SHOULD_be_replaced(self):
        # ARRANGE #
        pattern = r'PA[A-Z]*N'
        string_matching_pattern = 'PATTERN'
        string_not_matching_pattern = '<not matched by pattern>'
        string_matched_by_line_selector = '<MATCHED BY LINE MATCHER>'
        string_not_matched_by_line_selector = '<not matched by line matcher>'
        replacement_str = 'REPLACEMENT'
        sf = StringFormatter({
            'matches_pattern':
            string_matching_pattern,
            'replacement_str':
            replacement_str,
            'not_pattern':
            string_not_matching_pattern,
            'lm_match':
            string_matched_by_line_selector,
            'lm_no_match':
            string_not_matched_by_line_selector,
        })
        input_lines__tmpl = [
            '{matches_pattern} {lm_no_match}',
            '{matches_pattern} {lm_match}',
            '{not_pattern} {lm_no_match}',
            '{not_pattern} {lm_match}',
        ]
        output_lines__tmpl = [
            '{matches_pattern} {lm_no_match}',
            '{replacement_str} {lm_match}',
            '{not_pattern} {lm_no_match}',
            '{not_pattern} {lm_match}',
        ]
        input_lines = [sf.format(line) for line in input_lines__tmpl]

        output_lines = [sf.format(line) for line in output_lines__tmpl]

        lines_selector = LineMatcherSymbolContext.of_primitive(
            'LINES_SELECTOR_MATCHER',
            line_matchers.LineMatcherThatMatchesContentsSubString(
                string_matched_by_line_selector),
        )
        # ACT & ASSERT #
        self._check(
            pattern,
            replacement_str,
            lines_selector,
            input_lines,
            output_lines,
        )
Пример #2
0
 def plain_symbol_name_is_reserved_word(self, primitive_name: str) -> str:
     formatter = StringFormatter({
         'reserved_word': formatting.misc_name_with_formatting(misc_texts.RESERVED_WORD_NAME),
         'syntax_element': self._grammar.concept.syntax_element.name,
         'actual': formatting.keyword(primitive_name),
     })
     lines = [formatter.format(self._RESERVED_WORD__HEADER),
              '',
              formatter.format(self._RESERVED_WORD__LIST_HEADER),
              '']
     lines += [
         self._INDENT + formatting.keyword(reserved_word)
         for reserved_word in sorted(self._grammar.custom_reserved_words)
     ]
     return '\n'.join(lines)
Пример #3
0
        def cases_for(primitive_expr: str, the_operator: str) -> List[NameAndValue[str]]:
            sf = StringFormatter({
                'primitive_expr': primitive_expr,
                'operator': the_operator,
                'non_expr': ast.NOT_A_PRIMITIVE_EXPR_NAME_AND_NOT_A_VALID_SYMBOL_NAME,

            })

            return [
                NameAndValue(
                    'operator not followed by expression',
                    sf.format('{primitive_expr} {operator}'),
                ),
                NameAndValue(
                    'operator followed by non-expression',
                    sf.format('{primitive_expr} {operator} {non_expr}'),
                ),
                NameAndValue(
                    'operator followed by non-expression/two operators',
                    sf.format('{primitive_expr} {operator} {primitive_expr} {operator} {non_expr}'),
                ),
                NameAndValue(
                    '( at start of expr: missing )',
                    sf.format('( {primitive_expr} {operator} {primitive_expr} '),
                ),
                NameAndValue(
                    '( in middle of expr: missing )',
                    sf.format('( {primitive_expr} {operator} ( {primitive_expr} '),
                ),
            ]
Пример #4
0
        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)
Пример #5
0
 def cases_for_operator(the_prefix_operator: str) -> List[SourceCase]:
     sf = StringFormatter({
         'op': the_prefix_operator,
         'primitive_expr': primitive_expr_src,
         'space_after': space_after,
         'token_after': token_after,
     })
     return [
         SourceCase('first line is only primitive expr',
                    sf.format('{op} {primitive_expr}'),
                    SourceExpectation.is_at_end_of_line(1)),
         SourceCase(
             'first line is primitive expr with space around',
             sf.format(' {op}  {primitive_expr}{space_after}'),
             SourceExpectation.source_is_not_at_end(
                 current_line_number=1,
                 remaining_part_of_current_line=space_after[1:])),
         SourceCase(
             'expression is followed by non-expression',
             sf.format('{op} {primitive_expr} {token_after}'),
             SourceExpectation.source_is_not_at_end(
                 current_line_number=1,
                 remaining_part_of_current_line=token_after)),
         SourceCase(
             '( op primitive )',
             sf.format('( {op} {primitive_expr} )'),
             SourceExpectation.is_at_end_of_line(1),
         ),
         SourceCase(
             'op ( primitive )',
             sf.format('{op} ( {primitive_expr} )'),
             SourceExpectation.is_at_end_of_line(1),
         ),
         SourceCase(
             'no source after operator, but expr on following line',
             sf.format('{op}\n{primitive_expr}'),
             SourceExpectation.is_at_end_of_line(2),
         ),
     ]
Пример #6
0
        return _dir_error(path, '{PATH} exists, but is not {directory:a}')
    except NotADirectoryError:
        return _dir_error(path, 'Clash with existing file')

    return None


def _dir_error(path: DescribedPath, header_tmpl: str) -> TextRenderer:
    return path_err_msgs.line_header__primitive(
        _DIR_ERROR_FORMATTER.format(header_tmpl),
        path.describer,
    )


_DIR_ERROR_FORMATTER = StringFormatter({
    'PATH': syntax_elements.PATH_SYNTAX_ELEMENT.singular_name,
    'directory': file_types.DIRECTORY,
})

ERR = TypeVar('ERR')


def _create_file(file_path: pathlib.Path,
                 ensure_parent_path_is_existing_dir: Callable[[], Optional[ERR]],
                 error_renderer: Callable[[str], ERR],
                 operation_on_open_file: Callable[[TextIO], None],
                 ) -> Optional[ERR]:
    """
    :return: None iff success. Otherwise an error message.
    """
    try:
        file_path.lstat()
Пример #7
0
 def __init__(self, format_map: Optional[Mapping[str, Any]] = None):
     self._string_formatter = StringFormatter(format_map)
Пример #8
0
class TextParser:
    def __init__(self, format_map: Optional[Mapping[str, Any]] = None):
        self._string_formatter = StringFormatter(format_map)

    def format(
        self,
        template: str,
        extra: Optional[Mapping[str, Any]] = None,
    ) -> str:
        """
        Formats the given string using the format map given in the constructor.
        """
        return self._string_formatter.format(template, extra)

    def text(
        self,
        s: str,
        extra: Optional[Mapping[str, Any]] = None,
    ) -> docs.StringText:
        return docs.string_text(self.format(s, extra))

    def para(
        self,
        s: str,
        extra: Optional[Mapping[str, Any]] = None,
    ) -> docs.ParagraphItem:
        return docs.para(self.format(s, extra))

    def paras(
        self,
        s: str,
        extra: Optional[Mapping[str, Any]] = None,
    ) -> List[ParagraphItem]:
        return docs.paras(self.format(s, extra))

    def fap(
        self,
        s: str,
        extra: Optional[Mapping[str, Any]] = None,
    ) -> List[ParagraphItem]:
        """
        1. Text replacements according to `format_map` given to the constructor.
        2. parse result
        """
        return split_and_parse(self.format(s, extra))

    def fnap(
        self,
        s: str,
        extra: Optional[Mapping[str, Any]] = None,
    ) -> List[ParagraphItem]:
        """
        1. Text replacements according to `format_map` given to the constructor.
        2. normalize lines
        3. parse result
        """
        return normalize_and_parse(self.format(s, extra))

    def fnap__fun(
        self,
        s: str,
        extra: Optional[Mapping[str, Any]] = None,
    ) -> Callable[[], List[ParagraphItem]]:
        """A variant of fnap."""
        def ret_val() -> List[ParagraphItem]:
            return normalize_and_parse(self.format(s, extra))

        return ret_val

    def paragraph_items(
        self,
        s: str,
        extra: Optional[Mapping[str, Any]] = None,
    ) -> List[ParagraphItem]:
        return self.fnap(self.format(s, extra))

    def section(self,
                header_or_text,
                paragraphs_text: str,
                extra: Optional[Mapping[str, Any]] = None) -> docs.Section:
        """
        :param header_or_text: If a `str` it is formatted using `self.format`.
        :param paragraphs_text: Parsed using `self.fnap`.
        """
        header = header_or_text
        if not isinstance(header_or_text, docs.Text):
            header = docs.text(self.format(header_or_text, extra))
        return docs.section(header, self.fnap(paragraphs_text, extra))

    def section_contents(
        self,
        paragraphs_text: str,
        extra: Optional[Mapping[str, Any]] = None,
    ) -> docs.SectionContents:
        """
        :param paragraphs_text: Parsed using `self.fnap`.
        """
        return docs.section_contents(self.fnap(paragraphs_text, extra))
Пример #9
0
_SET_SPEC_ARGUMENT_2_SPEC = {
    defs.PHASE_SPEC__ACT: frozenset((_impl.Phase.ACT,)),
    defs.PHASE_SPEC__NON_ACT: frozenset((_impl.Phase.NON_ACT,)),
}

_ALL_PHASES = frozenset(_impl.Phase)


def parts_parser(phase_is_after_act: bool):
    return PartsParserFromEmbryoParser(EmbryoParser(phase_is_after_act),
                                       MainStepResultTranslatorForUnconditionalSuccess())


class _MissingUnsetKeywordOrVarNameErrorMessage(token_stream_parser.ErrorMessageGenerator):
    def message(self) -> str:
        return _SF.format('Expecting {unset_keyword} or {var_name}')


class _VarNameErrorMessage(token_stream_parser.ErrorMessageGenerator):
    def message(self) -> str:
        return _SF.format('Expecting {var_name}')


_MISSING_UNSET_KEYWORD_OR_VAR_NAME_ERROR_MESSAGE = _MissingUnsetKeywordOrVarNameErrorMessage()
_MISSING_VAR_NAME_ERROR_MESSAGE = _VarNameErrorMessage()

_SF = StringFormatter({
    'unset_keyword': defs.UNSET_IDENTIFIER,
    'var_name': defs.VAR_NAME_ELEMENT,
})
Пример #10
0
        def source_cases_for_expressions(primitive_expr: str,
                                         operator: str) -> List[SourceCase]:
            sf = StringFormatter({
                'primitive_expr': primitive_expr,
                'operator': operator,
                'quoted_operator': surrounded_by_soft_quotes(operator_source),
                'space_after': '           ',
                'quoted_string': surrounded_by_hard_quotes('quoted string'),

            })

            def source(template: str) -> str:
                return sf.format(template)

            return [
                SourceCase(
                    'first line is just infix op expr',
                    source('{primitive_expr} {operator} {primitive_expr}'),
                    SourceExpectation.is_at_end_of_line(1)
                ),
                SourceCase(
                    'first line is infix op expr, followed by space',
                    source('{primitive_expr} {operator} {primitive_expr}{space_after}'),
                    SourceExpectation.source_is_not_at_end(
                        current_line_number=1,
                        remaining_part_of_current_line=sf.format('{space_after}')[1:])
                ),
                SourceCase(
                    'infix op expr followed by non-operator',
                    source('{primitive_expr} {operator} {primitive_expr} {quoted_string}'),
                    SourceExpectation.source_is_not_at_end(
                        current_line_number=1,
                        remaining_part_of_current_line=sf.format('{quoted_string}'))
                ),
                SourceCase(
                    'infix op expr followed by primitive expression',
                    source('{primitive_expr} {operator} {primitive_expr} {primitive_expr}'),
                    SourceExpectation.source_is_not_at_end(
                        current_line_number=1,
                        remaining_part_of_current_line=sf.format('{primitive_expr}'))
                ),
                SourceCase(
                    'infix op expr followed by quoted operator',
                    source('{primitive_expr} {operator} {primitive_expr} {quoted_operator}'),
                    SourceExpectation.source_is_not_at_end(
                        current_line_number=1,
                        remaining_part_of_current_line=sf.format('{quoted_operator}'))
                ),
                SourceCase(
                    'first line is just infix op expr: inside ()',
                    source('( {primitive_expr} {operator} {primitive_expr} )'),
                    SourceExpectation.is_at_end_of_line(1)
                ),
                SourceCase(
                    'first primitive expr inside ()',
                    source('( {primitive_expr} ) {operator} {primitive_expr}'),
                    SourceExpectation.is_at_end_of_line(1)
                ),
                SourceCase(
                    'second primitive expr inside ()',
                    source('{primitive_expr} {operator} ( {primitive_expr} )'),
                    SourceExpectation.is_at_end_of_line(1)
                ),
                SourceCase(
                    'second expr on following line',
                    source('{primitive_expr} {operator}\n{primitive_expr}'),
                    SourceExpectation.is_at_end_of_line(2)
                ),
            ]
Пример #11
0
                         '{BEGIN_BRACE} fn1 fn2  {END_BRACE}'),
            NameAndValue('first line ok, multiple file names on second line',
                         '{BEGIN_BRACE} file-name\n'
                         'fn1 fn2\n'
                         '{END_BRACE}'),
        ]
        for must_be_on_current_line in [False, True]:
            for case in cases:
                with self.subTest(
                        source_case=case.name,
                        must_be_on_current_line=must_be_on_current_line):
                    source = _SF.format(case.value)
                    self._expect_parse_exception(source,
                                                 must_be_on_current_line)


_SF = StringFormatter({
    'BEGIN_BRACE':
    syntax.LITERAL_BEGIN,
    'END_BRACE':
    syntax.LITERAL_END,
    'FILE_MATCHER_SEPARATOR':
    syntax.FILE_MATCHER_SEPARATOR,
    'FILE_NAME':
    'a-file-name',
    'FILE_MATCHER':
    'file_matcher_symbol',
    'INVALID_FILE_MATCHER':
    NOT_A_VALID_SYMBOL_NAME_NOR_PRIMITIVE_GRAMMAR_ELEMENT_NAME,
})
Пример #12
0
from exactly_lib.util.str_.formatter import StringFormatter
from exactly_lib_test.test_resources.test_utils import NIE
from exactly_lib_test.util.test_resources.quoting import surrounded_by_hard_quotes

SINGLE_TOKEN_NAME = 'single_token_dir_name'
MULTI_LINE_NAME = 'a\nname\nthat\nspans\nmultiple\nlines\n'
SF = StringFormatter({
    'single_token_name':
    SINGLE_TOKEN_NAME,
    'quoted_multi_line_name':
    surrounded_by_hard_quotes(MULTI_LINE_NAME),
})

SOURCE_LAYOUT_CASES = [
    NIE(
        'all arguments on first line',
        input_value=SF.format('{single_token_name}'),
        expected_value=SINGLE_TOKEN_NAME,
    ),
    NIE(
        'path argument on following line',
        input_value=SF.format('\n {single_token_name}'),
        expected_value=SINGLE_TOKEN_NAME,
    ),
    NIE(
        'multi line path argument on following line',
        input_value=SF.format('\n {quoted_multi_line_name}'),
        expected_value=MULTI_LINE_NAME,
    ),
]
    return _EXIT_CODE_LINE_PREFIX + str(exit_code)


def _actual_exit_code_and_stderr_block(
        exit_code: int, stderr_contents: str) -> Renderer[MajorBlock]:
    def exit_code_block() -> Renderer[MinorBlock]:
        return blocks.MinorBlockOfSingleLineObject(
            line_objects.PreFormattedString(_actual_exit_code_line(exit_code)))

    minor_blocks = [
        exit_code_block(),
    ]
    if stderr_contents:
        minor_blocks.append(stderr_contents_block(stderr_contents))

    return comp_rend.MajorBlockR(combinators.SequenceR(minor_blocks))


_STRING_FORMATTER = StringFormatter({
    'exit_code': misc_texts.EXIT_CODE,
    'program': types.PROGRAM_TYPE_INFO.name,
})

_NON_ZERO_EXIT_CODE_HEADER = _STRING_FORMATTER.format(
    'Non-zero {exit_code} from {program}')

_UNABLE_TO_EXECUTE_HEADER = _STRING_FORMATTER.format(
    'Unable to execute {program}')

_EXIT_CODE_LINE_PREFIX = misc_texts.EXIT_CODE_TITLE + ': '