Example #1
0
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
Example #2
0
def main(mod: ModuleType) -> None:
    def _guess_kind(
        cls: t.Any,
        *,
        _builtins=set(id(v) for v in sys.modules["builtins"].__dict__.values()),
    ) -> t.Optional[Kind]:
        # is module?
        if hasattr(cls, "__loader__"):
            return None

        # is typed user_defined_type class or callable?
        if not hasattr(cls, "__name__"):
            return None

        if id(cls) in _builtins:
            return None
        if not callable(cls):
            return None

        if inspect.isclass(cls):
            return "object"
        return None

    w = runtime.get_walker(
        mod, recursive=True, aggressive=True, _guess_kind=_guess_kind
    )
    m = Module()
    o = sys.stderr if bool(os.environ.get("DEBUG", "")) else sys.stdout
    ctx = Context(w, is_minimum=bool(os.environ.get("MINIMUM", "")))
    print(emit(ctx, m=m), file=o)
Example #3
0
def gen(data: Data, *, m=None, indent="    "):
    m = m or Module(indent=indent)

    m.stmt("definitions:")
    with m.scope():
        m.stmt(f"{data.en_name}:")
        with m.scope():
            m.stmt(f"description: {data.ja_name}")
            m.stmt("type: string")
            m.stmt("enum:")
            with m.scope():
                for c in data.categories:
                    m.stmt(f"- {c.en_name}")
            m.stmt("x-ja-enum:")
            with m.scope():
                for c in data.categories:
                    m.stmt(f"- {c.ja_name}")
        m.sep()
    m.stmt("parameters:")
    with m.scope():
        m.stmt(f"{data.en_name}:")
        with m.scope():
            m.stmt(f"name: {data.en_name}")
            m.stmt("in: query")
            m.stmt(f"description: {data.ja_name}")
            m.stmt("type: string")
            m.stmt("enum:")
            with m.scope():
                for c in data.categories:
                    m.stmt(f"- {c.en_name}")
            m.stmt("x-ja-enum:")
            with m.scope():
                for c in data.categories:
                    m.stmt(f"- {c.ja_name}")
    return m
Example #4
0
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
Example #5
0
def gen(data: Enum, *, m=None, indent="    "):
    m = m or Module(indent=indent)

    m.stmt("definitions:")
    with m.scope():
        data.gen_definition(m=m)
        m.sep()
    m.stmt("parameters:")
    with m.scope():
        data.gen_parameter(m=m)
    return m
Example #6
0
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
Example #7
0
def gen(fn: t.Callable[..., t.Any], *, m=None, indent="\t"):
    m = m or Module(indent=indent)

    m.stmt("package main")
    m.sep()
    m.stmt("import (")
    with m.scope():
        m.stmt('"flag"')
        m.stmt('"fmt"')
        m.stmt('"log"')
    m.stmt(")")
    m.sep()

    spec = inspect.getfullargspec(fn)

    m.stmt("var (")
    with m.scope():
        for name, val in spec.annotations.items():
            if name == "return":
                continue
            m.stmt("""{} = {},""", name, resolve(name, val))
    m.stmt(")")
    m.sep()

    m.stmt("func main() {")
    with m.scope():
        m.stmt("flag.Parse()")
        m.stmt("if err := run(); err != nil {")
        with m.scope():
            m.stmt('log.Fatalf("+%v", err)')
        m.stmt("}")
    m.stmt("}")
    m.sep()

    m.stmt("func run() error {")
    with m.scope():
        for name in spec.annotations.keys():
            if name == "return":
                continue
            m.stmt("{} := *{}", name, name)
        m.sep()
        fn(m)
        m.stmt("return nil")
    m.stmt("}")
    return m
Example #8
0
def gen(typ: t.Type[t.Any], *, m=None, indent="    "):
    m = m or Module(indent=indent)
    def_name = get_name(typ)
    def_description = get_description(typ)

    m.stmt("definitions:")
    with m.scope():
        m.stmt(f"{def_name}:")
        with m.scope():
            m.stmt(f"description: {def_description}")
            m.stmt("type: string")
            m.stmt("enum:")
            with m.scope():
                for name in get_args(typ):
                    m.stmt(f"- {name}")

            metadata = get_metadata(typ)
            if Labels in metadata:
                m.stmt("x-ja-enum:")
                with m.scope():
                    for name in metadata[Labels].labels:
                        m.stmt(f"- {name}")
        m.sep()
    m.stmt("parameters:")
    with m.scope():
        m.stmt(f"{def_name}:")
        with m.scope():
            m.stmt(f"name: {name}")
            m.stmt("in: query")
            m.stmt(f"description: {def_description}")
            m.stmt("type: string")
            m.stmt("enum:")
            with m.scope():
                for name in get_args(typ):
                    m.stmt(f"- {name}")

            metadata = get_metadata(typ)
            if Labels in metadata:
                m.stmt("x-ja-enum:")
                with m.scope():
                    for name in metadata[Labels].labels:
                        m.stmt(f"- {name}")
    return m
Example #9
0
def gen(typ: t.Type[t.Any], *, m=None, indent="\t"):
    m = m or Module(indent=indent)

    m.stmt("package main")
    m.sep()
    m.stmt("import (")
    with m.scope():
        m.stmt('"flag"')
        m.stmt('"fmt"')
        m.stmt('"log"')
    m.stmt(")")
    m.sep()

    hints = t.get_type_hints(typ)

    m.stmt("var (")
    with m.scope():
        for name, val in hints.items():
            m.stmt("""{} = {},""", name, resolve(name, val))
    m.stmt(")")
    m.sep()

    m.stmt("func main() {")
    with m.scope():
        m.stmt("flag.Parse()")
        m.stmt("if err := run(); err != nil {")
        with m.scope():
            m.stmt('log.Fatalf("+%v", err)')
        m.stmt("}")
    m.stmt("}")
    m.sep()

    m.stmt("func run() error {")
    with m.scope():
        for name in hints.keys():
            m.stmt("{} := *{}", name, name)
        m.sep()
        m = typ.emit(m)
        m.stmt("return nil")
    m.stmt("}")
    return m
Example #10
0
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)')
Example #11
0
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
Example #12
0
from prestring.text import Module
from prestring.codeobject import Symbol


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 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


print(run(Module(indent="\t")))
Example #13
0
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
Example #14
0
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)
Example #15
0
        m.stmt("flag.Parse()")
        m.stmt("if err := run(); err != nil {")
        with m.scope():
            m.stmt('log.Fatalf("+%v", err)')
        m.stmt("}")
    m.stmt("}")
    m.sep()

    m.stmt("func run() error {")
    with m.scope():
        for name in spec.annotations.keys():
            if name == "return":
                continue
            m.stmt("{} := *{}", name, name)
        m.sep()
        fn(m)
        m.stmt("return nil")
    m.stmt("}")
    return m


def use(*, name: str, age: int) -> None:
    def gen(m):
        pass

    return gen


m = Module(indent="\t")
print(gen(use, m=m))
Example #16
0
 def emit(cls, m: Module) -> Module:
     m.stmt("// do something")
     return m
Example #17
0
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)
Example #18
0
        return m.scope()

    def parameters(self, *, m=None):
        m = m or self.m
        m.stmt("parameters:")
        return m.scope()


if __name__ == "__main__":
    season = Enum(
        name="season",
        description="四季",
        choices=[
            Choice(label="春", name="spring"),
            Choice(label="夏", name="summer"),
            Choice(label="秋", name="autumn"),
            Choice(label="冬", name="winter"),
        ],
    )

    m = Module(indent="  ")
    dsl = DSL(m)

    with dsl.definitions():
        dsl.enum.definition(season)
    m.sep()
    with dsl.parameters():
        dsl.enum.parameter(season)

    print(m)
Example #19
0
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
Example #20
0
def emit(ctx: Context, *, m: t.Optional[Module] = None) -> Module:
    w = ctx.walker
    m = m or Module()

    m.stmt("digraph G {")
    with m.scope():
        # setup
        m.stmt("graph [")
        with m.scope():
            m.stmt("compound = true")
        m.stmt("]")
        m.sep()
        m.stmt("node [")
        with m.scope():
            m.stmt('shape = "record"')
        m.stmt("]")
        m.sep()
        m.stmt("edge [")
        with m.scope():
            m.stmt('dir = "back"')
            m.stmt('arrowtail = "empty"')
            m.stmt("arrowsize = 0.65")
        m.stmt("]")
        m.sep()

        has_inheritance_types: t.List[t.Type[t.Any]] = []
        relations: t.List[
            t.Tuple[str, t.Type[t.Any], t.Type[t.Any]]
        ] = []  # name, from, to

        for cls in w.walk():
            emit_node(ctx, cls, m=m)
            if len(_get_mro(cls)) > 0:
                has_inheritance_types.append(cls)
                for parent_cls in _get_mro(cls):
                    w.append(parent_cls)

            # 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 None:
                    continue
                from_ = cls
                to = info.user_defined_type

                # todo: 1,0,*,?
                from_n = ""
                to_n = ""
                if info.is_container and info.container_type in ("list", "tuple"):
                    to_n = "*"
                label = metadata.get("label")
                relations.append((attrname, from_, to, (from_n, to_n, label)))

        # emit link (inheritance)
        for cls in has_inheritance_types:
            direct_parent_cls = cls.mro()[1]
            if _is_interface(cls):
                m.stmt(
                    f'{_get_type_name(direct_parent_cls)} -> {_get_type_name(cls)} [style="dashed"]'
                )
            else:
                m.stmt(f"{_get_type_name(direct_parent_cls)} -> {_get_type_name(cls)}")

        # emit link (relation)
        if len(relations) > 0:
            m.sep()
            m.stmt("edge [")
            with m.scope():
                m.stmt("constraint = false")
                m.stmt("minlen = 3")
                # todo: more styles
                m.stmt('arrowtail = "none"')
                # m.stmt('arrowtail = "normal"')
                # m.stmt('headlabel = "*"')
                # m.stmt('taillabel = "1"')
            m.stmt("]")
        for relname, from_, to, (from_n, to_n, label) in relations:
            attrs = []
            if label is not None:
                attrs.append(f'label = "{label}"')
            if to_n:
                attrs.append(f'headlabel = "{to_n}"')

            if attrs:
                attrs_str = f" [{', '.join(attrs)}]"
            else:
                attrs_str = ""
            m.stmt(f"{_get_type_name(from_)} -> {_get_type_name(to)}{attrs_str}")

    m.stmt("}")
    return m
Example #21
0
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
Example #22
0
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)