def run() -> Module: r = get_resolver() m = Module(indent="\t") classes = [Person, Person2] for item in walk(classes): m.stmt(f"type {goname(item.cls.__name__)} struct {{") with m.scope(): for name, typeinfo, _metadata in item.fields: metadata = t.cast(Metadata, _metadata) if metadata.get("default") == MISSING: metadata.pop("default") try: gotype = r.resolve_gotype( typeinfo.normalized) # todo: pointer except KeyError: gotype = goname(typeinfo.normalized.__name__) if metadata.get("pointer", False): gotype = f"*{gotype}" if metadata.get("inline", False): m.append(gotype) else: m.append(f"{goname(name)} {gotype}") if metadata: m.stmt(f" // {metadata}") else: m.stmt("") m.stmt("}") m.sep() return m
def load_config(m: Module, filename: Symbol) -> Symbol: LoadConfig = Symbol("LoadConfig") # todo: import config = Symbol("config") err = Symbol("err") m.stmt("{}, {} := {}", config, err, LoadConfig(filename)) m.stmt("if {} != nil {{", err) with m.scope(): m.stmt("return err") m.stmt("}") return config
def transform(source: str, *, indent="\t"): from prestring.text import Module m = Module(indent=indent) m.stmt("from {} import {}", m.__class__.__module__, m.__class__.__name__) m.stmt("m = Module(indent={!r})", indent) m = _transform(source, m=m, indent=indent) m.stmt("print(m)") return m
def run(m: Module) -> Module: filename = Symbol("filename") m.stmt("func Run({}: string) error {{", filename) # todo: with type with m.scope(): config = load_config(m, filename) m.stmt("return doSomething({})", config) # or "return nil" m.stmt("}") return m
def graph(d, pkg): import queue from prestring.text import Module m = Module() q = queue.Queue() q.put(pkg) seen = set() m.stmt("digraph {") with m.scope(): while not q.empty(): pkg = q.get() if pkg in seen: continue seen.add(pkg) m.stmt(f"// {pkg}") for next_pkg in d[pkg]: m.stmt(f"{pkg.replace('/', '_')} -> {next_pkg.replace('/', '_')}") q.put(next_pkg) m.sep() m.stmt("}") print(m)
def emit(targets, *, resources): m = Module(indent=" ") w = get_walker([]) for i, cls in enumerate(targets): name = resources[id(cls)] # xxx: m.stmt("resource {} {} {{", to_val(get_name(cls)), to_val(name)) with m.scope(): for name, info, metadata in w.for_type(cls).walk(): value = metadata["default"] if value is None: continue m.stmt("{} = {}", name, to_val(value)) m.stmt("}") if i < len(targets) - 1: m.sep() return m
def emit2(targets, *, resources): m = Module(indent=" ") w = get_walker([]) m.stmt('include classpath("application.conf")') m.stmt("queues {") with m.scope(): for i, cls in enumerate(targets): name = resources[id(cls)] # xxx: m.stmt("{} {{", name) with m.scope(): for name, info, metadata in w.for_type(cls).walk(): value = metadata["default"] if value is None: continue if isinstance(value, int): m.stmt("{} = {} seconds", name, value) else: m.stmt("{} = {}", name, to_val(value)) m.stmt("}") if i < len(targets) - 1: m.sep() m.stmt("}") return m
def emit(deps: t.Dict[str, t.List[str]], *, filename: t.Optional[str] = None) -> str: from prestring.text import Module deps = { name: { "task": x["task"].rsplit(".", 1)[-1], "depends": sorted(x["depends"]) } for name, x in deps.items() } suffix = "" if filename is None else f" -f {filename}" m = Module(indent="\t") m.stmt(f"DEP ?= {' '.join(deps.keys())}") m.stmt( f"PRE ?= {' '.join(['.pre/' + k.replace('/', '__') for k in deps.keys()])}" ) m.sep() m.stmt(f'CONT ?= PRE=$< DEP="" $(MAKE) _gen{suffix}') m.stmt("BULK_ACTION = .pre/bulk.action") m.sep() m.stmt("# goal task") m.stmt("default:") with m.scope(): m.stmt(f'@CONT="exit 0" $(MAKE) _gen{suffix}') m.sep() m.stmt("_gen: .pre $(DEP)") with m.scope(): m.stmt("@echo '**' $(PRE) '**' > /dev/stderr") m.stmt( "( $(foreach p,$(PRE),{ test $(p) -nt $(subst __,/,$(patsubst .pre/%,%,$(p))) && cat $(p); }; ) ) | sort | uniq > $(BULK_ACTION) || exit 0" ) m.stmt( """test -n "$$(cat $(BULK_ACTION))" && NOCHECK=1 python definitions.py $$(cat $(BULK_ACTION) | tr '\\n' ' ') || exit 0""" ) m.sep() m.stmt("# .pre files (sentinel)") for name, metadata in deps.items(): task = metadata["task"].split(".", 1)[-1] args = metadata["depends"] pre_file = f".pre/{name.replace('/', '__')}" m.stmt(f"{pre_file}: {' '.join(args)}") with m.scope(): m.stmt(f'echo "generate {task} -" > $@') m.sep() m.stmt("# actual dependencies") for name, metadata in deps.items(): task = metadata["task"].split(".", 1)[-1] args = metadata["depends"] pre_file = f".pre/{name.replace('/', '__')}" m.stmt(f"{name}: {pre_file}") with m.scope(): m.stmt(f"@$(CONT)") m.sep() m.stmt(".pre:") with m.scope(): m.stmt("mkdir -p $@") return str(m)
from prestring.text import Module m = Module(indent='\t') m.stmt('package main') m.sep() m.stmt('import (') with m.scope(): m.stmt('"log"') m.stmt('"net/http"') m.stmt('"os"') m.sep() m.stmt('"github.com/gin-gonic/gin"') m.stmt('_ "github.com/heroku/x/hmetrics/onload"') m.stmt(')') m.sep() m.stmt('func main() {') with m.scope(): m.stmt('port := os.Getenv("PORT")') m.sep() m.stmt('if port == "" {') with m.scope(): m.stmt('log.Fatal("$PORT must be set")') m.stmt('}') m.sep() m.stmt('router := gin.New()') m.stmt('router.Use(gin.Logger())') m.stmt('router.LoadHTMLGlob("templates/*.tmpl.html")') m.stmt('router.Static("/static", "static")') m.sep() m.stmt('router.GET("/", func(c *gin.Context) {') with m.scope(): m.stmt('c.HTML(http.StatusOK, "index.tmpl.html", nil)')
def emit_node(ctx: Context, cls: t.Type[t.Any], *, m: Module) -> Module: w = ctx.walker name = _get_type_name(cls) labelname = name if cls.mro()[1] == tx.Protocol: labelname = f"<<Interface>> {name}" methods = [] attributes = [] # todo: cache? seen = set() for parent_cls in _get_mro(cls): for attrname, _, _ in w.walk_fields(parent_cls, ignore_private=True): seen.add(attrname) for attrname, info, metadata in w.walk_fields(cls, ignore_private=True): if attrname in seen: continue if info.user_defined_type is not None: continue attributes.append(f"+ {attrname}: {_get_type_name(info.type_)}") # todo: walk_methods(cls, ignore_private=True) for attrname, attr in cls.__dict__.items(): if attrname.startswith("_"): continue if not callable(attr): continue # for inspect.signature() with PEP563 attr.__annotations__ = t.get_type_hints(attr) methods.append(f"+ {_get_method_signature(attrname, attr)}") m.stmt(f"{name} [") with m.scope(): m.stmt('shape = "none"') m.stmt(f'URL = "#{_get_html_id(name)}"') if ctx.is_minimum: m.stmt( f'label = <<TABLE BGCOLOR="gray95" BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="6" ><TR><TD>{labelname}</TD></TR></TABLE>>' ) else: m.stmt( f'label = <<TABLE BGCOLOR="gray95" BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="6" ><TR><TD>{labelname}</TD></TR><TR><TD ALIGN="LEFT" BALIGN="LEFT">{"<BR/>".join(attributes)}</TD></TR><TR><TD ALIGN="LEFT" BALIGN="LEFT">{"<BR/>".join(methods)}</TD></TR></TABLE>>' ) m.stmt("]") m.sep() return m
def emit(cls, m: Module) -> Module: m.stmt("// do something") return m
from __future__ import annotations from prestring.text import Module from prestring.go import goname from egoist.go.resolver import get_resolver from walker import walk class Person: name: str age: int info: Info class Info: memo: str r = get_resolver() m = Module(indent="\t") for item in walk([Person]): m.stmt(f"type {goname(item.cls.__name__)} struct {{") with m.scope(): for name, typeinfo, metadata in item.fields: gotype = r.resolve_gotype(typeinfo.normalized) # todo: pointer m.stmt(f"{goname(name)} {gotype}") m.stmt("}") print(m)