diff options
Diffstat (limited to 'debian/lib/python/debian_linux/utils.py')
-rw-r--r-- | debian/lib/python/debian_linux/utils.py | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/debian/lib/python/debian_linux/utils.py b/debian/lib/python/debian_linux/utils.py new file mode 100644 index 000000000..8f0463413 --- /dev/null +++ b/debian/lib/python/debian_linux/utils.py @@ -0,0 +1,80 @@ +import io +import os +import re +import textwrap +import typing + +import jinja2 + +from .debian import SourcePackage, BinaryPackage, TestsControl + + +class Templates(object): + dirs: list[str] + _cache: dict[str, str] + _jinja2: jinja2.Environment + + def __init__(self, dirs: list[str] = ["debian/templates"]) -> None: + self.dirs = dirs + + self._cache = {} + self._jinja2 = jinja2.Environment( + # autoescape uses HTML safe escaping, which does not help us + autoescape=False, + keep_trailing_newline=True, + trim_blocks=True, + undefined=jinja2.StrictUndefined, + ) + + def _read(self, name: str) -> typing.Any: + pkgid, name = name.rsplit('.', 1) + + for suffix in ['.j2', '.in', '']: + for dir in self.dirs: + filename = "%s/%s.%s%s" % (dir, pkgid, name, suffix) + if os.path.exists(filename): + with open(filename, 'r', encoding='utf-8') as f: + mode = os.stat(f.fileno()).st_mode + return (f.read(), mode, suffix) + + raise KeyError(name) + + def _get(self, key: str) -> typing.Any: + try: + return self._cache[key] + except KeyError: + self._cache[key] = value = self._read(key) + return value + + def get(self, key: str, context: dict[str, str] = {}) -> str: + value = self._get(key) + suffix = value[2] + + if context: + if suffix == '.in': + def subst(match): + return context[match.group(1)] + return re.sub(r'@([-_a-z0-9]+)@', subst, str(value[0])) + + elif suffix == '.j2': + return self._jinja2.from_string(value[0]).render(context) + + return value[0] + + def get_mode(self, key: str) -> str: + return self._get(key)[1] + + def get_control(self, key: str, context: dict[str, str] = {}) -> BinaryPackage: + return BinaryPackage.read_rfc822(io.StringIO(self.get(key, context))) + + def get_source_control(self, key: str, context: dict[str, str] = {}) -> SourcePackage: + return SourcePackage.read_rfc822(io.StringIO(self.get(key, context))) + + def get_tests_control(self, key: str, context: dict[str, str] = {}) -> TestsControl: + return TestsControl.read_rfc822(io.StringIO(self.get(key, context))) + + +class TextWrapper(textwrap.TextWrapper): + wordsep_re = re.compile( + r'(\s+|' # any whitespace + r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') # em-dash |