예제 #1
0
def run(*, path: str, disable_docstring) -> None:
    d = loading.loadfile(path)
    m = Module()
    a = Accessor(d, m, disable_docstring=disable_docstring)

    m.import_("typing", as_="t")
    m.sep()
    m.stmt("AnyService = t.Any  # TODO")
    m.stmt("AnyResource = t.Any  # TODO")
    m.sep()
    for rname, resource in a.resources.items():
        with m.class_(titleize(rname), ""):

            with m.method("__init__", "resource: AnyResource"):
                m.stmt("self.internal = resource")

            m.stmt("# methods")
            for mname, method, params in a.iterate_methods(resource):
                with m.method(mname, params):
                    a.emit_docstring(method["description"])
                    m.stmt(
                        f"""# {method["httpMethod"]}: {method["flatPath"]}""")
                    m.stmt(f"""# id: {method["id"]}""")
                    m.stmt(f"return self.internal.{mname}({params})")

            m.stmt("# nested resources")
            for srname, subresource in a.iterate_nested_resources(resource):
                with m.method(srname):
                    m.stmt(f"return self.internal.{srname}({params})")

            # m.stmt("# nested resources")
            # for mname, subresource in resource.get("resources", {}).items():
            #     params = LParams()
            #     for is_positional, (pname, parameter) in itertools.zip_longest(subresource.get("parameterOrder", []), subresource.get("parameters", {}).items()):
            #         if is_positional:
            #             params.append(pname)  # TODO type:
            #         else:
            #             params[pname] = None  # TODO type:
            #     with m.method(mname, params):
            #         docstring(subresource["description"])
            #         m.stmt(f"""# id: {subresource["id"]}""")
            #         m.stmt(f"return self.{mname}({params})")

    with m.class_("Service"):
        with m.method("__init__", "service: AnyService"):
            m.stmt("self.internal = service")

        for rname in a.resources.keys():
            with m.method(rname, return_type=titleize(rname)):
                m.stmt(f"return {titleize(rname)}(self.internal.{rname}())")

    with m.def_("build", "*args", "**kwargs", return_type="Service"):
        m.stmt("# TODO: use the signature of googleapiclient.discovery.build")
        m.submodule().from_("googleapiclient.discovery", "build")
        m.stmt(
            f"return Service(build({a.name!r}, {a.version!r}, *args, **kwargs))"
        )

    print(m)
예제 #2
0
def emit(ctx: Context):
    from prestring.python import Module

    m = Module()
    for name, cls in ctx.types.items():
        with m.class_(name):
            # TODO: omit class inheritance
            for field_name, field_type in t.get_type_hints(cls).items():
                # TODO: to pytype
                m.stmt(f"{field_name}: {field_type.__name__}")
    return m
from prestring.python import Module
from prestring.utils import LParams

m = Module()

with m.class_("A0"):
    params0 = LParams()
    with m.method("f0", params0):
        m.stmt("pass")

with m.class_("A1"):
    params1 = LParams()
    with m.method("f1", params1):
        m.stmt("pass")

params1.append_tail("*args")
print(m)

# class A0:
#     def f0(self): <- this (not f0(self,))
#         pass



# class A1:
#     def f1(self, *args):
#         pass

예제 #4
0
import inspect
from yaml.constructor import Constructor
from prestring.python import Module

m = Module()
m.from_("yaml.constructor", "Constructor")
m.sep()
with m.class_("WrappedConstructor", "Constructor"):
    with m.def_("wrap", "self", "path", "name", "node", "r"):
        with m.if_("r is None"):
            m.stmt("return r")
        m.stmt('# print("@", id(r), repr(r))')
        m.stmt("mem[id(r)] = node")
        m.stmt("return r")

    seen = set()
    for cls in Constructor.mro():
        for name, attr in cls.__dict__.items():
            if name in seen:
                continue
            seen.add(name)
            if name.startswith("construct_") and callable(attr):
                sigs = inspect.signature(attr)
                m.stmt("def {}{}:", name, sigs)
                with m.scope():
                    args = []
                    for v in sigs.parameters.values():
                        if v.name == "self":
                            continue
                        if v.default is inspect._empty:
                            args.append(str(v))
예제 #5
0
    val: int,
    default: int = 0,
    *,
    nickname: t.Optional[str] = None,
    debug: bool = False,
    **metadata: t.Optional[t.Any],
) -> None:
    pass


m = Module()
m.toplevel = m.submodule(import_unique=True)
m.sep()

spec = fnspec(f)
with m.class_("F"):
    for name, typ, kind in spec.parameters:
        if typ.__module__ != "builtins":
            m.toplevel.import_(typ.__module__)

        info = typeinfo(typ)
        rhs = spec.type_str_of(info.normalized)
        if info.is_optional:
            rhs = LazyFormat("typing.Optional[{}]", rhs)

        if kind == "var_kw":
            rhs = LazyFormat("typing.Dict[str, {}]", rhs)
        elif kind == "var_args":
            rhs = LazyFormat("typing.List[{}]", rhs)
        elif kind == "kw_defaults" or kind == "args_defaults":
            rhs = LazyFormat("{} = {}", rhs, spec.default_of(name))
예제 #6
0
    *,
    nickname: t.Optional[str] = None,
    debug: bool = False,
    **metadata: t.Optional[t.Any],
) -> None:
    pass


m = Module()
m.toplevel = m.submodule(import_unique=True)
m.sep()

# todo: alias
for fn in [f, g]:
    spec = fnspec(fn)
    with m.class_(pascalcase(spec.name)):
        for name, typ, kind in spec.parameters:
            if typ.__module__ != "builtins":
                m.toplevel.import_(typ.__module__)

            info = typeinfo(typ)
            rhs = spec.type_str_of(info.normalized)
            if info.is_optional:
                rhs = LazyFormat("typing.Optional[{}]", rhs)

            if kind == "var_kw":
                rhs = LazyFormat("typing.Dict[str, {}]", rhs)
            elif kind == "var_args":
                rhs = LazyFormat("typing.List[{}]", rhs)
            elif kind == "kw_defaults" or kind == "args_defaults":
                rhs = LazyFormat("{} = {}", rhs, spec.default_of(name))
예제 #7
0
def Person(m: Module, name: str) -> Module:
    # todo: import
    with m.class_(name, "BaseModel"):
        m.stmt("name: str")
        m.stmt("age : int = 0")
    return m
예제 #8
0
def gen_class_code(name: str, fields: t.List[V]) -> str:
    m = Module()
    with m.class_(name):
        _gen_init(m, name=name, fields=fields)
        _gen_repr(m, name=name, fields=fields)
    return str(m)
예제 #9
0
d = loading.loadfile(path / ("data/sqs/2012-11-05/service-2.json"))
"""
operations:
  <name>:
    name: <>
    input: {"shapee": <>}
    output: {"shape": <>,  "resultWrapper": <>}
    errors: {}
    documentation
"""

m = Module()
m.from_("__future__").import_("annotations")
m.sep()
m.stmt("# operations")
with m.class_("SQS"):
    for name, sd in d["operations"].items():
        with m.def_(
                name,
                f"input: {sd['input']['shape']}",
                return_type=sd["output"]["shape"] if "output" in sd else None,
        ):
            m.stmt("...")
m.stmt("# shapes")
with m.class_("SQS"):
    for name, sd in d["shapes"].items():
        with m.class_(name):
            # structure, type
            m.stmt("pass")

print(m)
예제 #10
0
import typing as t
from prestring.python import Module
from prestring.naming import titleize
from monogusa.web.codegen._fnspec import fnspec


def hello(name: str,
          *,
          age: int,
          nickname: t.Optional[str] = None) -> t.Dict[str, t.Any]:
    pass


m = Module()
fn = hello
spec = fnspec(fn)
with m.class_(titleize(fn.__name__)):
    if len(spec.keyword_arguments) == 0:
        m.stmt("pass")
    for name, typ, kind in spec.parameters:
        if kind.endswith("defaults"):
            m.stmt("{}: {} = {}", name, spec.type_str_of(typ),
                   spec.default_str_of(name))
        else:
            m.stmt("{}: {}", name, spec.type_str_of(typ))
print(m)
예제 #11
0
from prestring.python import Module

m = Module()
dataclasses = m.import_("dataclasses")

m.stmt("@{}", dataclasses.dataclass)
with m.class_("Person") as Person:
    m.stmt("name: str")
    m.stmt("age: int")

m.stmt(Person(name="foo", age=20))

print(m)

예제 #12
0
def Person(m: Module) -> None:
    with m.class_("Person"):
        m.stmt("name: str")
예제 #13
0
from prestring.python import Module

# 何が嫌だったのかを整理してみるか。

m = Module()

# こういう感じでクラス定義をするんだけれど。このクラスを利用する関数を書きづらい。
with m.class_("Person"):
    m.stmt("name: str")

# ここで "Person" って何? importされているの?と感じてしまう。
with m.def_("print_name", "p: Person"):
    m.stmt("print(p.name)")

# そしてここで定義したprint_name()も利用できない。何がおきているかと言うと。
#
# - "Person"というクラス定義を生成する記述は値ではないので持ち運べない
# - "print_name"という関数定義を生成する記述は値ではないので持ち運べない
#
# どれも値として扱えないことが問題? 例えば以下の様に関数で包むのはどうだろう。


def Person(m: Module) -> None:
    with m.class_("Person"):
        m.stmt("name: str")


# 何が嫌なのかと言えば、関数名とクラス名を二度書かないといけないと感じる点。
# ただ今度は値として持つことができる。
# 次にやりたいことはなんだろう?その値を使ってのコードとはなんのことだろう?
#
예제 #14
0
from prestring.python import Module
from prestring.utils import LParams

m = Module()

with m.class_("A0"):
    params0 = LParams()
    with m.method("f0", params0):
        m.stmt("pass")

with m.class_("A1"):
    params1 = LParams()
    with m.method("f1", params1):
        m.stmt("pass")

params1.append_tail("*args")
print(m)

# class A0:
#     def f0(self): <- this (not f0(self,))
#         pass

# class A1:
#     def f1(self, *args):
#         pass
예제 #15
0
def emit(filename: str, *, use_fullname: bool = False) -> None:
    from dictknife import loading
    from prestring.python import Module
    from detector import detect, Object, TypeInfo, ZERO, generate_annotations

    name_map = {}
    m = Module()
    m.toplevel = m.submodule()
    m.sep()

    def _pytype(info: TypeInfo,
                *,
                m=m,
                aliases: t.Dict[str, str] = {"typing": "t"}):
        if info is ZERO:
            module = aliases.get(t.__name__) or t.__name__
            return f"{module}.Any"

        if hasattr(info, "base"):
            module = aliases.get(info.base.__module__) or info.base.__module__
            m.toplevel.import_(info.base.__module__,
                               aliases.get(info.base.__module__))
            if info.base is t.Optional:
                return f"{module}.Optional[{_pytype(info.item)}]"
            elif info.base is t.List:
                return f"{module}.List[{_pytype(info.item)}]"
        elif hasattr(info, "type"):
            module = aliases.get(info.type.__module__) or info.type.__module__
            prefix = module + "."
            if module == "builtins":
                prefix = ""
            else:
                m.toplevel.import_(info.type.__module__,
                                   aliases.get(info.type.__module__))
            return prefix + info.type.__name__
        try:
            return name_map[id(info)]
        except KeyError:
            # FIXME: bug
            import sys

            print(f"something wrong: {info}", file=sys.stderr)
            return "UNKNOWN"

    d = loading.loadfile(filename)
    result = detect(d)
    annotations = generate_annotations(result,
                                       use_fullname=use_fullname,
                                       toplevel_name="toplevel")

    for info in result.history:
        if isinstance(info, Object):
            metadata = annotations["/".join(info.path)]
            name = metadata.get("after", metadata["before"])["name"]
            name_map[id(info)] = name

            m.stmt(f"# from: {'/'.join(info.path)}")
            with m.class_(name):
                for name, sub_info in info.props.items():
                    m.stmt("{}: {}", name, _pytype(sub_info))
    print(m)