from typing import List, Union from enum import Enum import re from .constants import * class MacroReplacementAtomIF: pass class FormatterProperty(MacroReplacementAtomIF, Enum): author = 'author' shortauthor = 'shortauthor' date = 'date' year = 'year' version = 'version', file_name = 'file_name' name = 'name' # class or package name repo_version = 'repo_version' pytex_version = 'pytex_version' class Argument(MacroReplacementAtomIF, Enum): one = 1 two = 2 three = 3 four = 4 five = 5 six = 6 class MacroReplacement(str): def __init__( self, replacement: str, format_type: str = '%', *args, **kwargs ): self.replacement: str = replacement self.format_type = '%', self.args = args self.kwargs = kwargs def make_format_args(self, formatter, *call_args): new_args = [] for arg in self.args: if type(arg) == FormatterProperty: try: new_args.append(getattr(formatter, arg.value)) except: raise NotImplementedError elif type(arg) == Argument: try: new_args.append(call_args[arg.value -1]) except: raise NotImplementedError elif type(arg) == str: new_args.append(arg) else: raise NotImplementedError new_kwargs = {} for kw in self.kwargs.keys(): if type(self.kwargs[kw]) == FormatterProperty: new_kwargs[kw] = getattr(formatter, self.kwargs[kw].value) elif type(self.kwargs[kw]) == Argument: new_kwargs[kw] = call_args[self.kwargs[kw].value -1] elif type(self.kwargs[kw]) == str: new_kwargs[kw] = self.kwargs[kw] else: raise NotImplementedError return new_args, new_kwargs def format(self, formatter, *call_args) -> str: args, kwargs = self.make_format_args(formatter, *call_args) if self.format_type == '%': if self.args: raise NotImplementedError # Currently, not supported return self.replacement % kwargs elif self.format_type == '{': return self.replacement.format( *args, **kwargs ) else: raise NotImplementedError class Macro: def __init__(self): raise NotImplementedError def matches(self, line: str) -> bool: raise NotImplementedError def apply(self, line: str, formatter) -> Union[str, List[str]]: raise NotImplementedError class BasicMacro(Macro): def __init__( self, macroname, num_args: int, macro_replacement: MacroReplacement ): self.macroname = macroname self.num_args = num_args self.macro_replacement: MacroReplacement = macro_replacement self._search_regex = re.compile(r'{keyword}\({arguments}(? bool: match = re.search(self._search_regex, line) if match is None: return False else: return True def apply(self, line: str, formatter) -> Union[str, List[str]]: match = re.search(self._search_regex, line) if match is None: raise NotImplementedError replacement = self.macro_replacement.format( formatter, match.groups() ) return line.replace( match.group(), replacement )