Coverage for tarjinja/iface.py: 92%
61 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-05 14:24 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-05 14:24 +0000
1import copy
2import fnmatch
3from collections.abc import Generator
4from logging import getLogger
6import braceexpand
8log = getLogger(__name__)
11class Input:
12 def __init__(self, ifn: str, **kwargs):
13 self.ifn = ifn
15 def walk(self) -> Generator[tuple[str, int, float], None, None]:
16 raise NotImplementedError("walk")
18 def readfile(self, fn: str) -> str:
19 raise NotImplementedError("readfile")
22class Filter:
23 def __init__(self, **kwargs):
24 pass
26 def render(self, s: str, vals: dict) -> str:
27 raise NotImplementedError("render")
29 def renderfn(self, s: str, vals: dict) -> Generator[str, None, None]:
30 return braceexpand.braceexpand(self.render(s, vals))
32 def strtr(self, strng: str, replace: dict) -> str:
33 # https://stackoverflow.com/questions/10931150/phps-strtr-for-python
34 buffer = []
35 i, n = 0, len(strng)
36 while i < n:
37 match = False
38 for s, r in replace.items():
39 if strng[i : len(s) + i] == s:
40 buffer.append(r)
41 i = i + len(s)
42 match = True
43 break
44 if not match:
45 buffer.append(strng[i])
46 i = i + 1
47 return "".join(buffer)
50class Output:
51 def __init__(self, ofn: str, **kwargs):
52 self.ofn = ofn
54 def writefile(self, fn: str, content: str, mode: int, ts: float | None = None):
55 raise NotImplementedError("writefile")
57 def finish(self):
58 log.debug("finished %s", self.ofn)
61class Pipeline:
62 def __init__(
63 self, inp: Input, filt: Filter, outp: Output, passpat: str | None = None
64 ):
65 self.inp = inp
66 self.filt = filt
67 self.outp = outp
68 self.passpat = passpat
70 def render(self, vals: dict):
71 for fnpat, mode, ts in self.inp.walk():
72 log.debug("walk %s (%o)", fnpat, mode)
73 content = self.inp.readfile(fnpat)
74 for fn in self.filt.renderfn(fnpat, vals):
75 if self.passpat is not None and fnmatch.fnmatch(fn, self.passpat): 75 ↛ 76line 75 didn't jump to line 76 because the condition on line 75 was never true
76 self.outp.writefile(fnpat, content, mode, ts)
77 else:
78 v = copy.deepcopy(vals)
79 v["fname"] = fn
80 ocont = self.filt.render(content, v)
81 log.debug("write %s", fn)
82 self.outp.writefile(fn, ocont, mode, ts)
83 self.outp.finish()