コード例 #1
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
コード例 #2
0
    def __init__(
        self,
        classes: t.List[t.Type[t.Any]],
        *,
        m: Module,
        metadata_handler: metadata_.MetadataHandlerFunction,
    ) -> None:
        from egoist.go.resolver import get_resolver

        self.m = m
        self.resolver = get_resolver(m)
        self.ctx = Context(
            m=m,
            resolver=self.resolver,
            _metadata_handler=metadata_handler,
        )
        self._walker = self.ctx.get_metashape_walker(classes)
コード例 #3
0
def emit(classes: t.List[t.Type[t.Any]], *, name: str = "main") -> Module:
    m = gofile(name)
    r = get_resolver(m)

    for item in walk(classes):
        if item.is_union:
            emit_union(m, item, resolver=r)
            m.sep()
        else:
            emit_struct(m, item, resolver=r)
            m.sep()
            if item.fields:
                emit_unmarshalJSON(m, item, resolver=r)
            m.sep()

    with m.func("main"):
        pass

    return m
コード例 #4
0
def run() -> Module:
    r = get_resolver()
    m = gofile("main")

    classes = [Person, Person2]

    for item in walk(classes):
        gopackage = get_gopackage(item.cls)
        if gopackage is not None:
            continue

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

                typ = typeinfo.raw
                if metadata.get("pointer", False):
                    typ = t.Optional[typ]
                gotype: str = r.resolve_gotype(typ)
                gopackage = get_gopackage(
                    typeinfo.normalized)  # todo: support composite

                if gopackage is not None:
                    gotype = f"{m.import_(gopackage)}.{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
コード例 #5
0
def clikit(
    env: Env,
    dry_run: bool,
    *,
    resolver: t.Optional[Resolver] = None,
    option_prefix: str = _PREFIX_DEFAULT,
) -> t.Iterator[Module]:
    if dry_run:
        logger.debug("dry run, %s skipped", __name__)
        yield env.m
        return

    from egoist.runtime import _REST_ARGS_NAME  # xxx
    from egoist.internal.prestringutil import goname
    from egoist.go.resolver import get_resolver

    m = env.m
    fn = env.fn
    spec = env.fnspec

    if len(spec.arguments) > 0:
        logger.info("%s(), positional arguments are ignored", fn.__name__)

    resolver = resolver or get_resolver(m)
    opt = m.symbol(option_prefix)

    description = None
    doc = inspect.getdoc(fn)
    if doc is not None:
        description = f"{env.fnspec.shortname} - {doc}"

    # TODO: support normal arguments
    m.package("main")
    m.import_("")
    m.stmt(f"// this file is generated by {__name__}")
    m.sep()

    m.stmt("// Option ...")
    with m.struct("Option"):
        for name, typ, kind in spec.keyword_arguments:
            m.stmt(f"{goname(name)} {resolver.resolve_gotype(typ)} // for `-{name}`")

        # NOTE: accessable via runtime.get_cli_rest_args()
        m.stmt(f"{goname(_REST_ARGS_NAME)} []string // cmd.Args")
    m.sep()

    with m.func("main"):
        m.stmt(f"{opt} := &Option{{}}")

        m.import_("flag")  # import:
        m.stmt(
            'cmd := flag.NewFlagSet("{}", flag.ContinueOnError)', env.fnspec.shortname,
        )
        if description is not None:
            m.stmt("cmd.Usage = func() {")
            with m.scope():
                m.import_("fmt")  # import:
                m.stmt(f"fmt.Fprintln(cmd.Output(), `{description}`)")
                m.stmt('fmt.Fprintln(cmd.Output(), "")')
                m.stmt('fmt.Fprintln(cmd.Output(), "Usage:")')
                m.stmt("cmd.PrintDefaults()")
            m.append("}")

        m.sep()

        for name, typ, kind in spec.keyword_arguments:
            arg = getattr(env.args, name)

            parse_method = resolver.resolve_parse_method(typ)
            help_usage = resolver.resolve_default(str, arg.help or "-")

            default = resolver.resolve_default(typ, arg.default)

            m.stmt(
                f'cmd.{parse_method}(&{opt}.{goname(name)}, "{name}", {default}, {help_usage})'
            )

        m.sep()

        m.import_("os")  # import:
        m.stmt("if err := cmd.Parse(os.Args[1:]); err != nil {")
        with m.scope():
            m.stmt("if err != flag.ErrHelp {")
            with m.scope():
                m.stmt("cmd.Usage()")
            m.stmt("}")
            m.stmt("os.Exit(1)")
        m.stmt("}")
        m.stmt(f"{opt}.Args = cmd.Args()")
        m.stmt(f"if err := run({opt}); err != nil {{")
        with m.scope():
            m.import_("log")  # import:
            m.stmt('log.Fatalf("!!%+v", err)')
        m.stmt("}")

    with m.func("run", f"{opt} *Option", returns="error"):
        m.stmt("// generated by `with runtime.generate(clikit): ...`")
        yield m
        if spec.return_type == type(None):  # noqa: E721
            m.return_("nil")
コード例 #6
0
def emit(classes: t.List[t.Type[t.Any]]) -> Module:
    m = gofile("main")
    r = get_resolver(m)

    for item in walk(classes):
        this = m.symbol(f"{item.type_.__name__[0].lower()}")
        this_type = f"{r.resolve_gotype(item.type_)}"
        this_type_pointer = f"*{this_type}"

        # func (ob *Ob) UnmarshalJSON(b []byte) error {
        b = m.symbol("b")
        m.stmt(
            f"func ({this} {this_type_pointer}) UnmarshalJSON({b} []byte) error {{"
        )
        with m.scope():

            # var err *maperr.Error
            err = m.symbol("err")
            maperr_pkg = m.import_("github.com/podhmo/maperr")
            m.stmt(f"var {err} *{maperr_pkg}.Error")
            m.sep()

            # var inner struct {
            #   ...
            # }
            m.stmt("// loading internal data")
            inner = m.symbol("inner")
            m.stmt(f"var {inner} struct {{")
            with m.scope():
                for name, typeinfo, metadata in item.fields:
                    if name.startswith("_"):
                        continue  # xxx:

                    gotype: str = r.resolve_gotype(typeinfo.raw)
                    m.append(f'{goname(name)} *{gotype} `json:"{name}"`')
                    m.stmt("// required" if metadata["required"] else "")
            m.stmt("}")

            # if rawErr := json.Unmarshal(b, &inner); rawErr != nil {
            # ...
            # }
            json_pkg = m.import_("encoding/json")
            raw_err = m.symbol("rawErr")
            with m.if_(
                    f"{raw_err} := {json_pkg}.Unmarshal(b, &{inner}); {raw_err} != nil"
            ):
                m.return_(err.addSummary(raw_err.Error()))
            m.sep()

            # if <field> != nil {
            #     ob.<field> = *<field>
            # } else {
            #     m.add(<field>, "required")
            # }
            m.stmt("// binding field value and required check")
            for name, typeinfo, metadata in item.fields:
                field = m.symbol(goname(name))
                with m.if_(f"{inner}.{field} != nil"):
                    m.stmt(f"{this}.{field} = *{inner}.{field}")
                if metadata["required"]:
                    with m.else_():
                        m.stmt(f'{err} = err.Add("{name}", "required")')
            m.sep()

            # return err.Untyped()
            m.return_(err.Untyped())
        m.stmt("}")
    return m
コード例 #7
0
import typing as t
from prestring.go.codeobject import gofile
from egoist.go.resolver import get_resolver
from emit import emit_enums

Op = t.Literal["add", "sub", "mul"]
Op.__name__ = "Op"

m = gofile("main")
resolver = get_resolver(m)
emit_enums(m, Op, resolver=resolver, name="op")

print(m)
コード例 #8
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)