Skip to content

reprexlite.parsing

Classes

LineType

Bases: Enum

An enum for different types of lines in text input to parse.

Parameters:

Name Type Description Default
CODE str

Line is code.

required
RESULT str

Line is the result of executing code.

required

Functions

auto_parse

auto_parse(input: str) -> Iterator[Tuple[str, LineType]]

Automatically parse input that is either doctest-style and reprex-style.

Source code in reprexlite/parsing.py
114
115
116
117
118
119
def auto_parse(input: str) -> Iterator[Tuple[str, LineType]]:
    """Automatically parse input that is either doctest-style and reprex-style."""
    if any(line.startswith(">>>") for line in input.split("\n")):
        yield from parse_doctest(input)
    else:
        yield from parse_reprex(input)

parse

parse(
    input: str,
    prompt: Optional[str],
    continuation: Optional[str],
    comment: Optional[str],
) -> Iterator[Tuple[str, LineType]]

Generator function that parses input into lines of code or results.

Parameters:

Name Type Description Default
input str

String to parse

required
prompt Optional[str]

Prefix used as primary prompt of code lines

required
continuation Optional[str]

Prefix used as continuation prompt of code lines

required
comment Optional[str]

Prefix used to indicate result lines

required

Yields:

Type Description
Tuple[str, LineType]

Iterator[Tuple[str, LineType]]: tuple of parsed line and line type

Source code in reprexlite/parsing.py
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
def parse(
    input: str,
    prompt: Optional[str],
    continuation: Optional[str],
    comment: Optional[str],
) -> Iterator[Tuple[str, LineType]]:
    """Generator function that parses input into lines of code or results.

    Args:
        input (str): String to parse
        prompt (Optional[str]): Prefix used as primary prompt of code lines
        continuation (Optional[str]): Prefix used as continuation prompt of code lines
        comment (Optional[str]): Prefix used to indicate result lines

    Yields:
        Iterator[Tuple[str, LineType]]: tuple of parsed line and line type
    """
    if not any((prompt, continuation, comment)):
        raise InvalidInputPrefixesError(
            "Cannot parse input if all of prompt, continuation, and comment are blank."
        )
    if len(prompt or "") != len(continuation or ""):
        raise PromptLengthMismatchError(
            f"Primary prompt ('{prompt}') and continuation prompt ('{continuation}') must be "
            "equal lengths."
        )

    for line_no, line in enumerate(input.split("\n")):
        # Case 1: With Prompt/Continuation, no Comment (e.g., doctest style)
        if prompt and continuation and not comment:
            if line.startswith(prompt):
                yield removeprefix(line, prompt), LineType.CODE
            elif line.startswith(continuation):
                yield removeprefix(line, continuation), LineType.CODE
            elif line == "":
                yield line, LineType.CODE
            else:
                yield line, LineType.RESULT

        # Case 2: No Prompt or Continuation, with Comment (e.g., reprex style)
        elif not prompt and not continuation and comment:
            if line.startswith(comment):
                yield removeprefix(line, comment), LineType.RESULT
            else:
                yield line, LineType.CODE

        # Case 3: Both Prompt/Contiuation and Comment
        elif prompt and continuation and comment:
            if line.startswith(prompt):
                yield removeprefix(line, prompt), LineType.CODE
            elif line.startswith(continuation):
                yield removeprefix(line, continuation), LineType.CODE
            elif line.startswith(comment):
                yield removeprefix(line, comment), LineType.RESULT
            elif line == "":
                yield line, LineType.CODE
            else:
                raise NoPrefixMatchError(
                    f"Line {line_no + 1} does not match any of prompt, continuation, or comment "
                    f"prefixes: '{line}'"
                )

        else:
            raise UnexpectedError("Unexpected case when using parse.")  # pragma: nocover

parse_doctest

parse_doctest(input: str) -> Iterator[Tuple[str, LineType]]

Wrapper around parse for parsing doctest-style input.

Source code in reprexlite/parsing.py
109
110
111
def parse_doctest(input: str) -> Iterator[Tuple[str, LineType]]:
    """Wrapper around [parse][reprexlite.parsing.parse] for parsing doctest-style input."""
    yield from parse(input=input, prompt=">>>", continuation="...", comment=None)

parse_reprex

parse_reprex(input: str) -> Iterator[Tuple[str, LineType]]

Wrapper around parse for parsing reprex-style input.

Source code in reprexlite/parsing.py
104
105
106
def parse_reprex(input: str) -> Iterator[Tuple[str, LineType]]:
    """Wrapper around [parse][reprexlite.parsing.parse] for parsing reprex-style input."""
    yield from parse(input=input, prompt=None, continuation=None, comment="#>")

removeprefix

removeprefix(s: str, prefix: str) -> str

Utility function to strip a prefix from a string, whether or not there is a single whitespace character.

Source code in reprexlite/parsing.py
12
13
14
15
16
17
18
19
20
21
22
23
def removeprefix(s: str, prefix: str) -> str:
    """Utility function to strip a prefix from a string, whether or not there is a single
    whitespace character.
    """
    if s.startswith(prefix + " "):
        return s[len(prefix) + 1 :]
    elif s.startswith(prefix):
        return s[len(prefix) :]
    else:
        raise UnexpectedError(  # pragma: nocover
            "removeprefix should not be called on input that does not match the prefix. "
        )