def depend_parameter_for(label, value): """Add a dependency on parameter initialization for ``value``. You need this when you want to use parameter value during starting up, where you need to sequence the access to be after parameter initialization. """ startup.add_func( lambda _: value, { '_': parameters.LABELS.parameters, 'return': label, }, ) return label
def define_binder(func, func_label, annotations=None, defaults=None): """Define a binder function and add it to ``startup``. This is a helper for this common pattern: .. code-block:: python def f(x: 'x') -> 'y': return x * x @startup def bind_f(x: 'x') -> 'f': if isinstance(x, Parameter): x = x.get() return functools.partial(f, x=x) It is shortened to: >>> bind_f = define_binder(f, 'f') """ # Since ``startup`` only calls ``bind`` once, it should be fine to # update ``defaults`` directly. def bind(**kwargs): return functools.partial(func, **_prepare(defaults, kwargs)) bind.__name__ = bind.__qualname__ = 'bind_%s' % func.__name__ bind_annotations = get_annotations(func) bind_annotations.update(annotations or ()) bind_annotations['return'] = func_label return startup.add_func(bind, bind_annotations)
def define_maker(func, annotations=None, defaults=None): """Define a maker function and add it to ``startup``. This is slightly more versatile than ``startup.add_func``. """ # Since ``startup`` only calls ``make`` once, it should be fine to # update ``defaults`` directly. def make(**kwargs): return func(**_prepare(defaults, kwargs)) make.__name__ = make.__qualname__ = 'make_%s' % func.__name__ make_annotations = get_annotations(func) make_annotations.update(annotations or ()) return startup.add_func(make, make_annotations)
"""Calculator client using parts.""" from startup import startup import g1.messaging.parts.clients from g1.apps import asyncs from g1.asyncs import kernels from examples import interfaces LABELS = g1.messaging.parts.clients.define_client() startup.add_func(interfaces.make_client, {'return': LABELS.client}) @startup def add_arguments(parser: asyncs.LABELS.parser) -> asyncs.LABELS.parse: parser.add_argument('op', choices=('add', 'sub', 'mul', 'div')) parser.add_argument('x', type=float) parser.add_argument('y', type=float) async def calculate(client, op, x, y): method = getattr(client.m, op) print('%s(%f, %f) == %f' % (op, x, y, await method(x=x, y=y))) def main(args: asyncs.LABELS.args, client: LABELS.client): kernels.run(calculate(client, args.op, args.x, args.y)) return 0
"""Calculator server using parts.""" from startup import startup import g1.asyncs.agents.parts import g1.messaging.parts.servers from g1.apps import asyncs from g1.asyncs import kernels from examples import interfaces LABELS = g1.messaging.parts.servers.define_server() startup.add_func(interfaces.make_server, {'return': LABELS.server}) def main(supervise_agents: g1.asyncs.agents.parts.LABELS.supervise_agents): kernels.run(supervise_agents) return 0 if __name__ == '__main__': asyncs.run(main)
) -> LABELS.args_not_validated: return parser.parse_args(argv[1:]) @startup def wait_for_args_validation( args: LABELS.args_not_validated, _: LABELS.validate_args, ) -> LABELS.args: return args startup.add_func( loggers.add_arguments, { 'parser': LABELS.parser, 'return': LABELS.parse, }, ) startup.add_func( loggers.configure_logging, {'args': LABELS.args}, ) # # Public interface. # def run(main, *, prog=None, argv=None):
def bind_label(source_label, target_label): startup.add_func(lambda x: x, {'x': source_label, 'return': target_label})