def test_walk_one__with_recursive2(): got = _walk(get_walker(Member, recursive=True)) want = { "Team": {"name": str(str), "members": str(t.List[Member])}, "Member": {"name": str(str), "team": str(Team)}, } assert want == got
def test_walk_list(): got = _walk(get_walker([Team, Member])) want = { "Team": {"name": str(str), "members": str(t.List[Member])}, "Member": {"name": str(str), "team": str(Team)}, } assert want == got
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 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)
def walk(classes: t.List[t.Type[t.Any]], *, _nonetype: t.Type[t.Any] = type(None)) -> t.Iterator[Item]: w = runtime.get_walker(classes) for cls in w.walk(kinds=["object", None]): if (getattr(cls, "__origin__", None) == t.Union and _nonetype not in cls.__args__): yield Item(type_=cls, fields=[], args=cls.__args__) for subtyp in cls.__args__: if subtyp.__module__ != "builtins": w.append(subtyp) continue fields: t.List[Row] = [] for name, info, _metadata in w.for_type(cls).walk( ignore_private=False): if name.startswith("_") and name.endswith("_"): continue filled_metadata: Metadata = metadata() filled_metadata.update(_metadata) if filled_metadata.get("default") == MISSING: filled_metadata.pop("default") if info.is_optional: filled_metadata["required"] = False if info.normalized.__module__ != "builtins": w.append(info.normalized) if hasattr(info.normalized, "__origin__"): # list, dict, etc.. for subtyp in t.get_args(info.normalized): if subtyp.__module__ != "builtins": w.append(subtyp) fields.append((name, info, filled_metadata)) yield Item(type_=cls, fields=fields, args=[])
def get_walker(guess_kind: t.Any = None) -> Walker: from metashape.runtime import get_walker guess_kind = guess_kind or _guess_kind return get_walker(aggressive=True, recursive=True, _depth=2, _guess_kind=guess_kind)
def test_walk_one__union(): from metashape.name import NewNamedType got = _walk(get_walker(NewNamedType("MemberOrTeam", t.Union[Member, Team]))) want = { "Member": {"name": str(str), "team": str(Team)}, "Team": {"name": str(str), "members": str(t.List[Member])}, } assert want == got
def run(name: str): m = import_module(name) w = get_walker(m, aggressive=True, recursive=False) def _to_str_typeinfo(info: typeinfo.TypeInfo) -> str: """ >>> _to_str_typeinfo(str) 'str' >>> _to_str_typeinfo(Literal["x", "y", "z"]) ' `x, y, z` ' >>> Color = Literal["Red", "Green", "Blue"] >>> _to_str_typeinfo(Color) '[Color](#Color)' """ if info.underlying != info.type_: # enum name = w.resolver.resolve_typename(info.type_) if name != "_GenericAlias": return f"[{name}](#{name})" args = [str(x) for x in typing.get_args(info.type_)] return f" `{', '.join(args)}` " name = info.underlying.__name__ if not info.user_defined_type: return name return f"[{name}](#{name})" for cls in w.walk(kinds=["object", "enum"]): print("") print(f"## {cls.__name__}") kind = guess_mark(cls) # todo: use resolve if kind == "enum": print("") print("```") args = typing.get_args(cls) print(f" {args[0]}") for x in args[1:]: print(f" | {x}") print("```") print("") else: doc = w.resolver.metadata.resolve_doc(cls, verbose=True) if doc is not None: print("") print(doc) print("") print("| name | type | description |") print("| :--- | :--- | :--- |") for name, info, metadata in w.walk_fields(cls): print( f"| {name} | {typeinfo.to_string(info, to_str=_to_str_typeinfo)} | {metadata.get('description') or ''}|" )
def walk(classes: t.List[t.Type[t.Any]]) -> t.Iterator[Item]: w = runtime.get_walker(classes) for cls in w.walk(kinds=["object", None]): fields: t.List[Row] = [] for name, typeinfo, metadata in w.for_type(cls).walk(): if metadata is None: metadata = {} if typeinfo.normalized.__module__ != "builtins": w.append(typeinfo.normalized) fields.append((name, typeinfo, metadata)) yield Item(cls=cls, fields=fields)
def run( filename: str, *, aggressive: bool = False, is_member: t.Optional[t.Callable[[t.Type[T]], bool]] = None, emit: t.Optional[EmitFunc] = None, ) -> None: m = import_module(filename, cwd=True) walker = get_walker(m, aggressive=aggressive) emit = emit or import_symbol("metashape.outputs.raw:emit") # xxx: logger.debug("collect members: %d", len(walker)) emit(walker, output=sys.stdout)
def run(dst: str): w = get_walker(aggressive=True, here=__name__) with output(dst, use_console=True, verbose=True, opener=partial(Module, indent="\t")) as fs: for cls in w.walk(): with fs.open(f"{snakecase(cls.__name__)}.go", "w") as m: ctx = Context(package="gen", w=w, m=m) emit_package_clause(ctx) m.sep() emit_simple_type_definition(ctx, cls)
def emit(items: t.Iterator[Item], *, name: str) -> Module: from metashape.runtime import get_walker m = Module(indent=" ") m.stmt('syntax = "proto3";') m.sep() m.stmt(f"package {name};") m.sep() m._import_area items = list(items) w = get_walker([]) classes: t.Dict[t.Type[t.Any], Item] = {} aliases: t.Dict[t.Any, Symbol] = {} for item in items: if item.kind in ("object", "enum", "service"): classes[item.type_] = item w.append(item.type_) if hasattr(item.type_, "PROTO_PACKAGE"): prefix = m.import_(item.type_.PROTO_PACKAGE) aliases[item.type_] = getattr(prefix, item.name) else: aliases[item.type_] = m.symbol(item.name) resolver = TypeResolver(m, aliases=aliases) for cls in w.walk(kinds=["object", None]): if hasattr(cls, "PROTO_PACKAGE"): continue item = classes[cls] if item.kind == "object": emit_class(m, item, w=w, resolver=resolver) elif item.kind == "enum": emit_enum(m, item, w=w, resolver=resolver) elif item.kind == "service": emit_service(m, item, w=w, resolver=resolver) m.sep() for item in items: if item.kind == "list": emit_list(m, item, w=w, resolver=resolver) return 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 run(dst: str): import sys m = sys.modules[__name__] w = get_walker(m, aggressive=True) with output(dst, use_console=True, verbose=True, opener=partial(Module, indent="\t")) as fs: for cls in w.walk(): if issubclass(cls, Context): continue with fs.open(f"{snakecase(cls.__name__)}.go", "w") as m: ctx = Context(package="gen", w=w, m=m) emit_package_clause(ctx) m.sep() emit_simple_type_definition(ctx, cls)
from metashape.declarative import mark from metashape.runtime import get_walker from metashape.outputs.openapi import codegen @mark class Person: name: str age: int extra: "Extra" @mark class Extra: memo: str # main codegen(get_walker([Person]))
from __future__ import annotations import typing as t from metashape.declarative import shape from metashape import runtime @shape class Person: name: str age: int father: t.Optional[Person] mother: t.Optional[Person] w = runtime.get_walker(Person) assert [Person] == list(w.walk())
import dataclasses from metashape.declarative import ignore, field @ignore @dataclasses.dataclass class Service: name: str outdated: bool = False class XXXServices: foo: Service = field(default=Service(name="foo")) bar: Service = field(default=Service(name="bar")) boo: Service = field(default=Service(name="boo")) if __name__ == "__main__": from metashape.runtime import get_walker for cls in get_walker(aggressive=True).walk(): print(cls)
from metashape.runtime import graph, get_walker g = graph(get_walker(aggressive=True)) g.User.deps # => {"tweets": Tweet, "favorites": Tweet} g.User.rdeps # => {Twitter: {"author": "tweets", "favorited": "favorites"}}
# self references class Person: name: str spouse: t.Optional[Person] # reverse: spouse, synmetric one-to-one friends: t.Set[Person] # reverse: friends, synmetric many-to-many manager: t.Optional[Person] # reverse: employees, one side of non-synmetric employees: t.Set[Person] # reverse: manager, another side of non-synmetric # multiple relationships between two entities class User: name: str tweets: t.Set[Tweet] # reverse: author favorites: t.Set[Tweet] # reverse: favorited class Tweet: text: str author: User # reverse tweets favorited: t.Set[User] # reverse favorites import sys from metashape.runtime import get_walker from metashape.outputs.openapi import emit w = get_walker([User, Person], aggressive=True, recursive=True) emit(w, output=sys.stdout)
def test_walk_one__container(): got = _walk(get_walker(t.List[Member])) want = { "Member": {"name": str(str), "team": str(Team)}, } assert want == got
import typing as t from metashape.runtime import get_walker from prestring.python import Module from prestring.utils import LazyFormat, LazyArgumentsAndKeywords from typestr import typestr class Hello: name: str age: int nickname: t.Optional[str] = None m = Module() w = get_walker([Hello]) for cls in w.walk(): name = w.resolver.resolve_typename(cls) args = [] for fieldname, info, metadata in w.for_type(cls).walk(): # todo: default if "default" in metadata: args.append( LazyFormat( "{}: {} = {}", fieldname, typestr(info.raw), metadata["default"] ) ) else: args.append(LazyFormat("{}: {}", fieldname, typestr(info.raw))) with m.def_(name, LazyArgumentsAndKeywords(args)): m.stmt("...")
import typing as t from common import User class WUser(User): nickname: t.Optional[str] = None def get_module(typ: t.Type[t.Any]) -> str: return getattr(typ, "__module__") assert get_module(User) == "common" assert get_module(WUser) == "__main__" # accessing from metashape.runtime import get_walker # noqa 401 w = get_walker([WUser]) for cls in w.walk(): for name, info, metadata in w.for_type(cls).walk(): print(name, metadata)
def get_walker(classes: t.List[t.Type[t.Any]]) -> Walker: from metashape.runtime import get_walker from metashape.analyze.config import Config return get_walker(classes, config=Config(option=Config.Option(strict=False)))
from metashape import runtime class Person: name: str age: int w = runtime.get_walker([Person]) for cls in w.walk(): print(cls) for name, typeinfo, metadata in w.walk_fields(cls): print("\t", name, typeinfo.raw, metadata)
def test_walk_one(): got = _walk(get_walker(Team)) want = {"Team": {"name": str(str), "members": str(t.List[Member])}} assert want == got
from __future__ import annotations import typing as t import sys from metashape.runtime import get_walker from metashape.outputs.openapi import emit class Team: name: str members: t.List[Person] class Person: team: Team name: str age: int nickname: t.Optional[str] parents: t.List[Person] emit(get_walker(aggressive=True), output=sys.stdout)
import typing as t import sys import string from metashape.runtime import get_walker from metashape.outputs.openapi import scan, emit class Person: name: str age: int ctx = scan(get_walker(aggressive=True)) class _Formatter(string.Formatter): def __init__(self): self.d = {} def get_value(self, key: str, args: list, kwargs: dict) -> object: self.d[key] = key return self.d[key] def extract_parameters(f, fmt_string) -> t.List[str]: f.format(fmt_string) r = list(f.d.keys()) f.d.clear() return r
primary_number: str state_abbreviation: str street_name: str street_predirection: str street_suffix: str zipcode: str class Metadatum: carrier_route: str congressional_district: str county_fips: str county_name: str dst: bool elot_sequence: str elot_sort: str latitude: float longitude: float precision: str rdi: str record_type: str time_zone: str utc_offset: int zip_type: str w = get_walker(Data, aggressive=True, recursive=True) targets = list(w.walk()) for cls in targets: print(cls)
class Person: name: str = "foo" age: int = 20 from metashape.runtime import get_walker from prestring.naming import untitleize d = {} w = get_walker(aggressive=True) for cls in w.walk(): props = {} for name, _, _ in w.for_type(cls).walk(): # camelCase? props[name] = getattr(cls, name) typename = w.resolver.resolve_typename(cls) d[untitleize(typename)] = props from dictknife import loading loading.dumpfile(d, format="yaml")
from __future__ import annotations import typing as t import conf from metashape.runtime import get_walker from metashape.analyze.walker import Walker from metashape.analyze.collector import Collector from dictknife import loading @Collector def collect(cls: t.Type[t.Any], *, w: t.Optional[Walker]): props = {} for name, typeinfo, metadata in w.for_type(cls).walk(): fieldname = w.resolver.metadata.resolve_name(metadata, default=name) props[fieldname] = collect(getattr(cls, name), w=w) return props w = get_walker(conf.Toplevel) for cls in w.walk(): loading.dumpfile(collect(cls, w=w))