aiomas.rpc — aiomas 0.2.0 documentation

# `aiomas.rpc`

This module implements remote procedure calls (RPC) on top of request-reply channels (see `aiomas.channel`).

RPC connections are represented by instances of `RpcClient` (one for each side of a `aiomas.channel.Channel`). They provide access to the functions served by the remote side of the channel via `Proxy` instances. Optionally, they can provide their own RPC service (via `rpc_service()`) so that the remote side can make calls as well.

An RPC service is defined by a `Router`. A router resolves paths requested by the remote side. It can also handle sub-routers (which allows you to build hierarchies for nested calls) and is able to perform a reverse-lookup of a router (mapping a fuction to its path).

Routers provide the functions and methods of dictionaries or class instances. Dict routers can be created by passing a dictionary to `Router`. For classes, you create a `Service` instance as rpc class attribute. This creates a Descriptor which then creates a new router instance for each class instance.

Functions that should be callable from the remote side must be decorated with `expose()`; `Router.expose()` and `Service.expose()` are aliases for it.

`aiomas.rpc.` `open_connection`(addr, *, router=None, add_to=None, **kwds)

  Return an `RpcClient` connected to addr.

  This is a convenience wrapper for `aiomas.channel.open_connection()`. All keyword arguments (kwds) are forwared to it.

  You can optionally pass a router to allow the remote site to call back to us.

  If you want to cleanly cancel all `rpc_service()` tasks created for each connection made to router, you can pass a `set` via add_to. All tasks will then be append to it.

`aiomas.rpc.` `start_server`(addr, router, add_to=None, **kwds)

  Start a server socket on host:port and create an RPC service with the provided handler for each new client.

  This is a convenience wrapper for `aiomas.channel.start_server()`. All keyword arguments (kwds) are forwared to it.

  router must be a `Router` instance for the `rpc_service()` that is started for each new connection.

  If you want to cleanly cancel all `rpc_service()` tasks created for each connection made to router, you can pass a `set` via add_to. All tasks will then be append to it.

  Raise a `ValueError` if handler is not decorated properly.

`aiomas.rpc.` `rpc_service`(router, channel)

  Serve the functions provided by the `Router` router via the `Channel` channel.

  Forward errors raised by the handler to the caller.

  Stop running when the connection closes.

`aiomas.rpc.` `expose`(func)

  Decorator that enables RPC access to the decorated function.

  func will not be wrapped but only gain an `__rpc__` attribute.

class `aiomas.rpc.` `DictWrapper`(router, dict)

  Wrapper for dicts so that they can be used as RPC routers.

class `aiomas.rpc.` `Router`(obj)

  The Router resolves paths to functions provided by their object obj (or its children). It can also perform a reverse lookup to get the path of the router (and the router’s obj).

  The obj can be a class, an instance or a dict.

  `obj` = None

    The object to which this router belongs to.

  `name` = None

    The name of the router (empty for root routers).

  `parent` = None

    The parent router or `None` for root routers.

  `path`

    The path to this router (without trailing slash).

  `resolve`(path)

    Resolve path and return the corresponding function.

    path is a string with path components separated by / (without trailing slash).

    Raise a `LookupError` if no handler function can be found for path or if the function is not exposed (see `expose()`).

  static `expose`(func)

    Alias for `expose()`.

  `add`(name)

    Add the sub-router name (stored at `self.obj.<name>`) to this router.

    Convenience wrapper for `set_sub_router()`.

  `set_sub_router`(router, name)

    Set self as parent for the router named name.

class `aiomas.rpc.` `Service`(sub_routers=())

  A Data Descriptor that creates a new `Router` instance for each class instance to which it is set.

  The attribute name for the Service should always be rpc:

      class Spam:
          rpc = aiomas.rpc.Service()

  You can optionally pass a list with the attribute names of classes with sub-routers. This required to build hierarchies of routers, e.g.:

      class Eggs:
          rpc = aiomas.rpc.Service()

      class Spam:
          rpc = aiomas.rpc.Service(['eggs'])

          def __init__(self):
              self.eggs = Eggs()  # Instance with a sub-router

  static `expose`(func)

    Alias for `expose()`.

class `aiomas.rpc.` `RpcClient`(channel, router=None, add_to=None)

  The RpcClient provides proxy objects for remote calls via its `remote` attribute.

  channel is a `Channel` instance for communicating with the remote side.

  If router is not `None`, it will also start its own RPC service so the other side can make calls to us as well.

  If you want to cleanly cancel all `rpc_service()` tasks created for each connection made to router, you can pass a `set` via add_to. All tasks will then be append to it.

  `remote`

    A `Proxy` for remote methods.

  `close`()

    Close the connection.

class `aiomas.rpc.` `Proxy`(channel, path)

  Proxy object for remote objects and functions.

  `__getattr__`(name)

    Return a new proxy for name.

  `__call__`(*args, **kwargs)

    Call the remote method represented by this proxy and return its result.

    The result is a future, so you need to `yield from` it in order to get the actual return value (or exception).