• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Hekxsler / pudding / 26163864792

20 May 2026 12:54PM UTC coverage: 92.385% (-0.9%) from 93.254%
26163864792

Pull #5

github

web-flow
Merge f197fa31e into a91d4e7d1
Pull Request #5: Feature/specifiy output

1286 of 1392 relevant lines covered (92.39%)

0.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.74
pudding/processor/context.py
1
"""Module defining context class."""
2

3
import re
1✔
4

5
from pudding.exceptions import SyntaxError, NameError, IndexError
1✔
6

7
from ..datatypes import String, Varname
1✔
8
from ..reader.reader import Reader
1✔
9
from ..writer import Writer
1✔
10
from .grammar import Grammar
1✔
11
from .triggers import TriggerQueue
1✔
12

13

14
class Context:
1✔
15
    """Class containing context for the processor.
16

17
    :var grammars: Grammars defined in the syntax.
18
    :var queue: Queue for triggers created by enqueued statements.
19
    :var variables: Variables defined in the syntax.
20
    """
21

22
    def __init__(self, reader: Reader, writer: Writer) -> None:
1✔
23
        """Init for Context class.
24

25
        :param reader: Reader with content of the file to convert.
26
        :param writer: Writer for generating output.
27
        """
28
        self.grammars: dict[str, Grammar] = {}
1✔
29
        self.queue: TriggerQueue = TriggerQueue()
1✔
30
        self.variables: dict[str, str] = {}
1✔
31
        self.reader = reader
1✔
32
        self.writer = writer
1✔
33

34
    def get_grammar(self, name: str) -> Grammar:
1✔
35
        """Get a grammar by name.
36

37
        :param name: Name of the grammar to retrieve.
38
        :raises SyntaxError: If grammar is not defined.
39
        """
40
        grammar = self.grammars.get(name)
1✔
41
        if not grammar:
1✔
42
            raise SyntaxError(f'Grammar "{name}" is not defined.')
×
43
        return grammar
1✔
44

45
    def get_var(self, varname: Varname) -> str:
1✔
46
        """Get a variable by name.
47

48
        :param name: Name of the variable to retrieve.
49
        :returns str: Defined regex pattern as a string.
50
        :raises NameError: If variable is not defined.
51
        """
52
        value = self.variables.get(varname.value)
1✔
53
        if not value:
1✔
54
            raise NameError(
×
55
                f'Variable "{varname.value}" is not defined. (line {varname.line})'
56
            )
57
        return value
1✔
58

59
    def replace_string_vars(self, string: String) -> str:
1✔
60
        """Replace variables in a string with the last matched values.
61

62
        :param string: String to replace vars in.
63
        :param context: The current context.
64
        :returns: The string with replaced values.
65
        """
66
        # get vars in string
67
        string_vars = re.findall(r"\$(\d+)", string.value)
1✔
68
        if len(string_vars) == 0:
1✔
69
            return string.value
1✔
70
        if self.reader.last_match is None:
1✔
71
            raise SyntaxError("String variables used before an expression matched.")
×
72
        new_string = string.value
1✔
73
        matches = self.reader.last_match.groups()
1✔
74
        # check for enough matches
75
        highest_number = max(string_vars, key=lambda x: int(x))
1✔
76
        if int(highest_number) >= len(matches):
1✔
77
            raise IndexError(
×
78
                "Not enough matches to replace string variables. "
79
                f"Need {highest_number} but only found {len(matches)}."
80
            )
81
        # replace vars in string
82
        for number in string_vars:
1✔
83
            assert isinstance(number, str)
1✔
84
            new_string = re.sub(
1✔
85
                rf"\${number}(?!\d+)", matches[int(number)], new_string, count=1
86
            )
87
        return new_string
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc