aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--muppet/puppet/ast.py104
1 files changed, 104 insertions, 0 deletions
diff --git a/muppet/puppet/ast.py b/muppet/puppet/ast.py
index 2ce3c35..b527c23 100644
--- a/muppet/puppet/ast.py
+++ b/muppet/puppet/ast.py
@@ -722,3 +722,107 @@ def build_ast(form: Any) -> Puppet:
case default:
logger.warning("Unhandled item: %a", default)
return PuppetParseError(default)
+
+
+def generate_template() -> None:
+ """
+ Output code for a formater class.
+
+ Each formatter needs to implement a rather large number of
+ methods, and keeping track of them all is hard. This generates a
+ ready-to-use template.
+
+ .. code-block:: sh
+
+ python -m muppet.puppet.ast > muppet/puppet/format/NAME.py
+ """
+
+ def pyind(level: int) -> str:
+ """Indent string for python code."""
+ return ' ' * 4 * level
+
+ subclasses = sorted(subclass.__name__ for subclass in Puppet.__subclasses__())
+
+ def tokenize_class(s: str) -> list[str]:
+ """Split a camel or pascal cased string into words."""
+ out: list[str] = []
+ current: str = ''
+ for c in s:
+ if c.isupper():
+ if current.isupper():
+ current += c
+ else:
+ out.append(current)
+ current = c
+ else:
+ current += c
+ out.append(current)
+
+ if out[0] == '':
+ out = out[1:]
+
+ return out
+
+ def setup_override() -> None:
+ print('''
+from typing import (
+ TypeVar,
+ Callable,
+)
+
+
+F = TypeVar('F', bound=Callable[..., object])
+
+# TODO replace this decorator with
+# from typing import override
+# once the target python version is changed to 3.12
+
+
+def override(f: F) -> F:
+ """
+ Return function unchanged.
+
+ Placeholder @override annotator if the actual annotation isn't
+ implemented in the current python version.
+ """
+ return f
+
+
+'''.lstrip())
+
+ print('''"""
+__
+
+TODOFormatter
+TODO_RETURN_TYPE
+"""''')
+
+ print()
+ print('import logging')
+ print('from .base import Serializer')
+ print('from muppet.puppet.ast import (')
+ for subclass in subclasses:
+ print(pyind(1) + subclass + ',')
+ print(')')
+
+ setup_override()
+
+ print()
+ print()
+ print('logger = logging.getLogger(__name__)')
+ print()
+ print()
+
+ print('class TODOFormatter(Serializer[TODO_RETURN_TYPE]):')
+ print(pyind(1) + '"""TODO document me!!!"""')
+ for subclass in subclasses:
+ func_name = '_'.join(tokenize_class(subclass)).lower()
+ print()
+ print(pyind(1) + '@override')
+ print(pyind(1) + '@classmethod')
+ decl = f"def _{func_name}(cls, it: {subclass}, indent: int) -> TODO_RETURN_TYPE:"
+ print(pyind(1) + decl)
+
+
+if __name__ == '__main__':
+ generate_template()