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 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 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 add_server_process(app: App) -> None: 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) app.add_directive("add_server_process", _define)