def includeme(app: App): app.include("discovery") # TODO: spawn, when using # TODO: spawn, when dry_run=False only def _register(): from discovery import get_discovery port = None if app.registry.dry_run: logger.info("dry run, %s skipped", NAME) get_discovery().register("gofmtrpc", url=f"http://127.0.0.1:{port}") return from egoist.internal.netutil import find_free_port from util import spawn_with_connection port = find_free_port() get_discovery().register("gofmtrpc", url=f"http://127.0.0.1:{port}") argv = ["gofmtrpc", "-addr", f":{port}"] p, _ = spawn_with_connection(argv, sentinel_option="-sentinel") import atexit def _shutdown(): logger.info("terminate gofmtrpc") with p: p.terminate() atexit.register(_shutdown) app.action(NAME, _register)
def define_something(app: App) -> None: import sys name = "define_something" seen = False print("** on decorator", file=sys.stderr) def _register_something(app: App, something: t.Any) -> AnyFunction: nonlocal seen if not seen: seen = True def _register() -> AnyFunction: name = something.__name__ print("*** {name}, on register".format(name=name), file=sys.stderr) app.action((name, something.__name__), _register) return _register app.add_directive(name, _register_something) def _include() -> None: nonlocal seen if seen: print("** on include", file=sys.stderr) # for conflict check app.action(name, _include)
def includeme(app: App): app.include("discovery") # TODO: only spawn, when using def _register(): import shutil from egoist.internal.netutil import find_free_port from discovery import get_discovery import util sentinel = util.create_sentinel_file() port = find_free_port() get_discovery().register("gofmtrpc", url=f"http://127.0.0.1:{port}") assert shutil.which("gofmtrpc") argv = [ "gofmtrpc", "-addr", f":{port}", "-sentinel", sentinel, ] p = util.ConnectedProcess().spawn(argv, sentinel=sentinel) import atexit def _shutdown(): logger.info("terminate gofmtrpc") with p: p.terminate() atexit.register(_shutdown) app.action(NAME, _register)
def makegen( app: App, *, tasks: t.Optional[t.List[str]] = None, rootdir: t.Optional[str] = None, out: t.Optional[str] = None, relative: bool = True, ) -> None: import contextlib import os from egoist.components.tracker import get_tracker from egoist.commands.generate import generate app.commit(dry_run=True) if not bool(os.environ.get("VERBOSE", "")): logging.getLogger("prestring.output").setLevel(logging.WARNING) generate(app, tasks=tasks, rootdir=rootdir) root_path = get_root_path(app.settings, root=rootdir) deps = get_tracker().get_dependencies(root=root_path, relative=relative) with contextlib.ExitStack() as s: out_port: t.Optional[t.IO[str]] = None if out is not None: out_port = s.enter_context(open(out, "w")) print(emit(deps, filename=getattr(out_port, "name", None)), file=out_port)
def define_foo(app: App, fn: AnyFunction, name: str) -> AnyFunction: """*** define foo ***""" print(app, fn, "foo", name) def _register(): print("!") app.registry.generators[name].append(fn) app.action(fn.__name__, _register) return fn
def includeme(app: App) -> None: from egoist.experimental.serverprocess.lazyparams import find_free_port, create_sentinel_file app.include("egoist.experimental.serverprocess") # for add_server_process app.add_server_process( "gofmtrpc -addr :{port} -sentinel {sentinel}", params=dict(port=find_free_port, sentinel=create_sentinel_file), name=NAME, )
def setup_server(app: App) -> None: from egoist.ext.serverprocess.lazyparams import find_free_port, create_sentinel_file app.include("egoist.ext.serverprocess") # for add_server_process app.add_server_process( "uvicorn server:app --port {port}", params=dict(port=find_free_port), name="api-server", env={"SENTINEL": create_sentinel_file}, )
def includeme(app: App) -> None: app.include("directives.define_server_process") from rpcutil import find_free_port, create_sentinel_file app.define_server_process( "gofmtrpc -addr :{port} -sentinel {sentinel}", params=dict(port=find_free_port, sentinel=create_sentinel_file), name="gofmtrpc", )
def _register_something(app: App, something: t.Any) -> AnyFunction: nonlocal seen if not seen: seen = True def _register() -> AnyFunction: name = something.__name__ print("*** {name}, on register".format(name=name), file=sys.stderr) app.action((name, something.__name__), _register) return _register
def define_server_process(app: App): def _define( app: App, fmt: str, *, name: str, urlfmt: str = "http://{host}:{port}", host: str = "127.0.0.1", port: t.Optional[int] = None, params: t.Optional[t.Dict[str, t.Callable[[], object]]] = None, ): def _register(): nonlocal host nonlocal port import shlex import atexit from discovery import get_discovery from rpcutil import find_free_port kwargs = {k: fn(app) for k, fn in (params or {}).items()} if port is None: port = kwargs.get("port") or find_free_port() if "host" in kwargs: host = kwargs.get["host"] argv = shlex.split(fmt.format(**kwargs)) url = urlfmt.format(host=host, port=port) get_discovery().register(name, url=url) if app.registry.dry_run: logger.info("dry run, %s skipped", name) return from spawn import spawn_with_connection p, _ = spawn_with_connection(argv) def _shutdown(): # xxx: logger.info("terminate %s", name) with p: p.terminate() atexit.register(_shutdown) app.action(("define_server_process", name), _register) app.include("discovery") app.add_directive("define_server_process", _define)
def describe(app: App) -> None: import json import inspect from egoist.langhelpers import get_fullname_of_type, get_fullname_of_callable app.commit(dry_run=False) definitions: t.Dict[str, t.Dict[str, t.Union[str, t.List[str]]]] = {} delayed_include_mapping = app.delayed_include_mapping for kit, fns in app.registry.generators.items(): for fn in fns: name = get_fullname_of_callable(fn) summary = (inspect.getdoc(fn) or "").strip().split("\n", 1)[0] definitions[name] = {"doc": summary, "generator": kit} if fn in delayed_include_mapping: definitions[name]["include_when"] = [ get_fullname_of_callable(dep) if callable(dep) else (_app.module.__name__ + dep if dep.startswith(".") else dep) for _app, dep in delayed_include_mapping[fn] ] factories = { name: [get_fullname_of_type(x) for x in xs] # type: ignore for name, xs in app.registry.factories.items() } empty_context = app.context_factory() current_directives = set(name for name, attr in app.context.__dict__.items() if callable(attr)) append_directives = current_directives.difference( empty_context.__dict__.keys()) append_directives = append_directives.difference(["run"]) d = { "definitions": definitions, "components": factories, "directives": { name: get_fullname_of_type(getattr(app.context, name)) for name in append_directives }, } print(json.dumps(d, indent=2, ensure_ascii=False))
def generate(app: App, *, tasks: t.Optional[t.List[str]] = None, rootdir: t.Optional[str] = None, dry_run: bool = False) -> None: root_path = get_root_path(app.settings, root=rootdir) app.commit(dry_run=dry_run) app.context.queue.clear() # xxx: clear action_list: t.List[t.Callable[..., t.Any]] = [] included_after_commit_list: t.List[t.Union[str, t.Callable[..., t.Any]]] = [] for kit, fns in app.registry.generators.items(): walk_or_module = app.maybe_dotted(kit) if callable(walk_or_module): walk = walk_or_module elif hasattr(walk_or_module, "walk"): walk = walk_or_module.walk # type: ignore else: # TODO: genetle error message raise ConfigurationError("{kit!r} is not callable") if not tasks: sources = {fn.__name__: fn for fn in fns} else: sources = {fn.__name__: fn for fn in fns if fn.__name__ in tasks} action_list.append(partial(walk, sources, root=root_path)) # for app.include_when() delayed_include_mapping = app.delayed_include_mapping for fn in sources.values(): if fn in delayed_include_mapping: for _app, path in delayed_include_mapping[fn]: _app.include(path) included_after_commit_list.append(path) app.delayed_include_mapping.clear() # xxx: clear if len(included_after_commit_list) > 0: app.shallow_commit() for action in action_list: action()
def includeme(self, app: App) -> None: """callback for app.include()""" # for information used by describe() directive = partial(self.register) update_wrapper(directive, self.define_fn) app.add_directive(self.name, directive) def _include() -> None: if self.seen or not self.requires: return seen = app._aggressive_import_cache for path in self.requires: if path in seen: continue app.include(path) app.action(self.name, _include)
def includeme(app: App): app.include("discovery") # TODO: only spawn, when using def _register(): import sys import pathlib from egoist.internal.netutil import find_free_port from discovery import get_discovery import util sentinel = util.create_sentinel_file() server_py = pathlib.Path(__file__).absolute().with_name("server.py") port = find_free_port() get_discovery().register("HELLO", url=f"http://127.0.0.1:{port}") argv = [ sys.executable, server_py, "--port", str(port), "--host", "127.0.0.1", "--sentinel", sentinel, ] p = util.ConnectedProcess().spawn(argv, sentinel=sentinel) import atexit def _shutdown(): logger.info("terminate HELLO") with p: p.terminate() atexit.register(_shutdown) app.action(NAME, _register)
def includeme(app: App) -> None: app.include(".tracker") actual: FSFactory = create_fs app.register_factory(NAME, actual) for_dry_run: FSFactory = create_dummy_fs app.register_dryurn_factory(NAME, for_dry_run)
from egoist.app import App, SettingsDict, parse_args settings: SettingsDict = {"rootdir": "cmd/", "here": __file__} app = App(settings) app.include("egoist.commands.generate") app.include("egoist.directives.define_cli") @app.define_cli("egoist.generators.clikit:walk") def hello(*, name: str) -> None: """hello message""" from egoist.generators.clikit import runtime, clikit with runtime.generate(clikit): runtime.printf("hello %s\n", name) if __name__ == "__main__": for argv in parse_args(sep="-"): app.run(argv)
from egoist.app import App, SettingsDict settings: SettingsDict = {"root": "cmd/", "here": __file__} app = App(settings) app.include("egoist.directives.define_cli") @app.define_cli("egoist.generate.clikit:walk") def hello(*, name: str) -> None: """hello message""" from egoist.generate.clikit import runtime, clikit with runtime.generate(clikit): runtime.printf("hello %s\n", name) if __name__ == "__main__": app.run()
def includeme(app: App) -> None: app.include("egoist.components.fs")
from egoist.app import App, SettingsDict, parse_args settings: SettingsDict = {"rootdir": "output", "here": __file__} app = App(settings) app.include("egoist.directives.define_file") @app.define_file("egoist.generators.filekit:walk", suffix=".txt") def hello() -> None: from egoist.generators.filekit import runtime with runtime.create_file() as wf: print("hello world", file=wf) if __name__ == "__main__": for argv in parse_args(sep="-"): app.run(argv)
from __future__ import annotations import typing as t from egoist.app import App app = App(settings={"here": __file__, "rootdir": ""}) app.include("egoist.directives.define_struct_set") @app.define_struct_set("egoist.generators.structkit:walk") # type: ignore def models__models() -> None: from egoist.generators.structkit import runtime, structkit import objects @runtime.set_metadata_handler def metadata_handler(cls: t.Type[t.Any], *, name: str, info: t.Any, metadata: runtime.Metadata) -> None: """with form""" metadata["tags"] = { "json": [name.rstrip("_")], "form": [name.rstrip("_")] } with runtime.generate(structkit, classes=[objects.Person]) as m: m.package("models") if __name__ == "__main__": app.run()
def setup_server(app: App) -> None: from egoist.ext.serverprocess.lazyparams import find_free_port, create_sentinel_file app.include("egoist.ext.serverprocess") # for add_server_process
def includeme(app: App) -> None: app.register_factory(NAME, Tracker) app.register_dryurn_factory(NAME, Tracker)
def includeme(app: App) -> None: app.include("egoist.components.tracker") app.include("egoist.directives.add_subcommand") app.include("egoist.commands.generate") app.add_subcommand(setup, fn=makegen)
def _define( app: App, fmt: str, *, name: str, urlfmt: str = "http://{host}:{port}", host: str = "127.0.0.1", port: t.Optional[t.Union[int, str]] = None, params: t.Optional[t.Dict[str, LazyParam]] = None, env: t.Optional[t.Dict[str, LazyParam]] = None, cwd: t.Union[str, pathlib.Path, None] = None, nowait: bool = False, ) -> None: app.include("egoist.experimental.serverprocess.components.discovery") app.include("egoist.experimental.serverprocess.components.httpclient") def _register() -> None: nonlocal host nonlocal port import shlex import atexit from .components.discovery import get_discovery from .lazyparams import find_free_port, create_sentinel_file if app.registry.dry_run: kwargs: t.Dict[str, t.Any] = { k: "xxx" for k in (params or {}).keys() } environ = {k: "xxx" for k in (env or {}).keys()} port = "xxx" sentinel = "xxx" else: kwargs = {k: fn(app) for k, fn in (params or {}).items()} environ = {k: fn(app) for k, fn in (env or {}).items()} if port is None: port = (kwargs.get("port") or environ.get("port") or environ.get("PORT") or find_free_port(app)) elif "port" not in kwargs: kwargs["port"] = port if "host" in kwargs: host = kwargs["host"] elif "host" not in kwargs: kwargs["host"] = host sentinel = ( # xxx kwargs.get("sentinel") or environ.get("SENTINEL") or ("" if nowait else create_sentinel_file(app))) argv = shlex.split(fmt.format(**kwargs)) url = urlfmt.format(host=host, port=port) get_discovery().register(name, url=url) if app.registry.dry_run: logger.info("dry run, skip starting server process, %s", name) return from .spawn import spawn_with_connection p, _ = spawn_with_connection(argv, sentinel=sentinel, environ=environ, cwd=cwd, check=not nowait) def _shutdown() -> None: # xxx: logger.info("terminate %s", name) with p: p.terminate() atexit.register(_shutdown) app.action(("add_server_process", name), _register)
def includeme(app: App) -> None: app.register_factory(NAME, Discovery) app.register_dryurn_factory(NAME, Discovery)
from __future__ import annotations import typing as t from egoist.app import App, SettingsDict, parse_args from egoist.generators.structkit.runtime import metadata, field from egoist.generators.structkit.runtime import set_metadata_handler, Metadata settings: SettingsDict = {"rootdir": "", "here": __file__} app = App(settings) app.include("egoist.directives.define_struct_set") app.include("egoist.directives.define_cli") class Author: name: str # createdAt: datetime.date class Article: title: str author: t.Optional[Author] content: str comments: t.List[Comment] = field(metadata=metadata(required=False)) class Comment: author: Author content: str @app.define_struct_set("egoist.generators.structkit:walk")
def includeme(app: App) -> None: app.include("egoist.directives.add_subcommand") app.add_subcommand(setup, fn=hello)
def hello(app: App) -> None: app.commit(dry_run=False) print("do something")
@directive(name="define_foo", requires=["egoist.commands.describe"]) def define_foo(app: App, fn: AnyFunction, name: str) -> AnyFunction: """*** define foo ***""" print(app, fn, "foo", name) def _register(): print("!") app.registry.generators[name].append(fn) app.action(fn.__name__, _register) return fn if __name__ == "__main__": app = App() app.include("__main__.define_foo") @app.define_foo("xxx") def yyy(): print("yyy") @app.define_foo("xxx") def zzz(): print("zzz") print("s") app.commit() yyy() zzz() print("e")
def includeme(app: App) -> None: app.register_factory(NAME, _create_http_client) app.register_dryurn_factory(NAME, _create_fake_http_client)