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

Hekxsler / pudding / 20368087396

19 Dec 2025 11:04AM UTC coverage: 83.669% (-4.6%) from 88.305%
20368087396

Pull #1

github

web-flow
[all]: Fix typing
Pull Request #1: Increase performance with custom node class

1081 of 1292 relevant lines covered (83.67%)

0.84 hits per line

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

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

3
import re
1✔
4

5
from ..datatypes.varname import Varname
1✔
6

7
from ..datatypes.string import String
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
STRING_VAR_RE = r"([^\d]?\$(\d+)[^\$]?)"
1✔
14
# match chars before and after to not match $1 and $10 when replacing $1
15

16

17
class Context:
1✔
18
    """Class containing context for the processor.
19

20
    :var grammars: Grammars defined in the syntax.
21
    :var queue: Queue for triggers created by enqueued statements.
22
    :var variables: Variables defined in the syntax.
23
    """
24

25
    def __init__(self, content: str, writer: Writer) -> None:
1✔
26
        """Init for Context class.
27

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

37
    def get_grammar(self, name: str) -> Grammar:
1✔
38
        """Get a grammar by name.
39

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

48
    def get_var(self, varname: Varname) -> str:
1✔
49
        """Get a variable by name.
50

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

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

65
        :param string: String to replace vars in.
66
        :param context: The current context.
67
        :returns: The string with replaced values.
68
        """
69
        string_vars = re.findall(STRING_VAR_RE, string.value)
1✔
70
        if len(string_vars) == 0:
1✔
71
            return string.value
1✔
72
        if self.reader.last_match is None:
1✔
73
            raise RuntimeError(
×
74
                "Can not replace variables, because no expression matched yet."
75
            )
76
        new_string = string.value
1✔
77
        matches = self.reader.last_match.groups()
1✔
78
        for replace, number in string_vars:
1✔
79
            assert isinstance(replace, str)
1✔
80
            if int(number) >= len(matches):
1✔
81
                raise IndexError(
×
82
                    f"Not enough matches in {matches} to replace variable '${number}'."
83
                )
84
            replacement = replace.replace(f"${number}", matches[int(number)], 1)
1✔
85
            new_string = re.sub(re.escape(replace), replacement, new_string, 1)
1✔
86
        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