forked from M-Labs/artiq
doc: fixes and add sync_struct docstrings
This commit is contained in:
parent
0c2e960c85
commit
56ea62b936
|
@ -1,3 +1,16 @@
|
||||||
|
"""This module helps synchronizing a mutable Python structure owned and
|
||||||
|
modified by one process (the *publisher*) with copies of it (the
|
||||||
|
*subscribers*) in different processes and possibly different machines.
|
||||||
|
|
||||||
|
Synchronization is achieved by sending a full copy of the structure to each
|
||||||
|
subscriber upon connection (*initialization*), followed by dictionaries
|
||||||
|
describing each modification made to the structure (*mods*).
|
||||||
|
|
||||||
|
Structures must be PYON serializable and contain only lists, dicts, and
|
||||||
|
immutable types. Lists and dicts can be nested arbitrarily.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from operator import getitem
|
from operator import getitem
|
||||||
|
|
||||||
|
@ -9,6 +22,9 @@ _init_string = b"ARTIQ sync_struct\n"
|
||||||
|
|
||||||
|
|
||||||
def process_mod(target, mod):
|
def process_mod(target, mod):
|
||||||
|
"""Apply a *mod* to the target, mutating it.
|
||||||
|
|
||||||
|
"""
|
||||||
for key in mod["path"]:
|
for key in mod["path"]:
|
||||||
target = getitem(target, key)
|
target = getitem(target, key)
|
||||||
action = mod["action"]
|
action = mod["action"]
|
||||||
|
@ -27,6 +43,16 @@ def process_mod(target, mod):
|
||||||
|
|
||||||
|
|
||||||
class Subscriber:
|
class Subscriber:
|
||||||
|
"""An asyncio-based client to connect to a ``Publisher``.
|
||||||
|
|
||||||
|
:param notifier_name: Name of the notifier to subscribe to.
|
||||||
|
:param target_builder: A function called during initialization that takes
|
||||||
|
the object received from the publisher and returns the corresponding
|
||||||
|
local structure to use. Can be identity.
|
||||||
|
:param notify_cb: An optional function called every time a mod is received
|
||||||
|
from the publisher. The mod is passed as parameter.
|
||||||
|
|
||||||
|
"""
|
||||||
def __init__(self, notifier_name, target_builder, notify_cb=None):
|
def __init__(self, notifier_name, target_builder, notify_cb=None):
|
||||||
self.notifier_name = notifier_name
|
self.notifier_name = notifier_name
|
||||||
self.target_builder = target_builder
|
self.target_builder = target_builder
|
||||||
|
@ -78,6 +104,29 @@ class Subscriber:
|
||||||
|
|
||||||
|
|
||||||
class Notifier:
|
class Notifier:
|
||||||
|
"""Encapsulates a structure whose changes need to be published.
|
||||||
|
|
||||||
|
All mutations to the structure must be made through the ``Notifier``. The
|
||||||
|
original structure must only be accessed for reads.
|
||||||
|
|
||||||
|
In addition to the list methods below, the ``Notifier`` supports the index
|
||||||
|
syntax for modification and deletion of elements. Modification of nested
|
||||||
|
structures can be also done using the index syntax, for example:
|
||||||
|
|
||||||
|
>>> n = Notifier([])
|
||||||
|
>>> n.append([])
|
||||||
|
>>> n[0].append(42)
|
||||||
|
>>> n.read
|
||||||
|
[[42]]
|
||||||
|
|
||||||
|
This class does not perform any network I/O and is meant to be used with
|
||||||
|
e.g. the ``Publisher`` for this purpose. Only one publisher at most can be
|
||||||
|
associated with a ``Notifier``.
|
||||||
|
|
||||||
|
:param backing_struct: Structure to encapsulate. For convenience, it
|
||||||
|
also becomes available as the ``read`` property of the ``Notifier``.
|
||||||
|
|
||||||
|
"""
|
||||||
def __init__(self, backing_struct, root=None, path=[]):
|
def __init__(self, backing_struct, root=None, path=[]):
|
||||||
self.read = backing_struct
|
self.read = backing_struct
|
||||||
if root is None:
|
if root is None:
|
||||||
|
@ -92,6 +141,9 @@ class Notifier:
|
||||||
# All modifications must go through them!
|
# All modifications must go through them!
|
||||||
|
|
||||||
def append(self, x):
|
def append(self, x):
|
||||||
|
"""Append to a list.
|
||||||
|
|
||||||
|
"""
|
||||||
self._backing_struct.append(x)
|
self._backing_struct.append(x)
|
||||||
if self.root.publish is not None:
|
if self.root.publish is not None:
|
||||||
self.root.publish(self.root, {"action": "append",
|
self.root.publish(self.root, {"action": "append",
|
||||||
|
@ -99,6 +151,9 @@ class Notifier:
|
||||||
"x": x})
|
"x": x})
|
||||||
|
|
||||||
def insert(self, i, x):
|
def insert(self, i, x):
|
||||||
|
"""Insert an element into a list.
|
||||||
|
|
||||||
|
"""
|
||||||
self._backing_struct.insert(i, x)
|
self._backing_struct.insert(i, x)
|
||||||
if self.root.publish is not None:
|
if self.root.publish is not None:
|
||||||
self.root.publish(self.root, {"action": "insert",
|
self.root.publish(self.root, {"action": "insert",
|
||||||
|
@ -106,6 +161,11 @@ class Notifier:
|
||||||
"i": i, "x": x})
|
"i": i, "x": x})
|
||||||
|
|
||||||
def pop(self, i=-1):
|
def pop(self, i=-1):
|
||||||
|
"""Pop an element from a list. The returned element is not
|
||||||
|
encapsulated in a ``Notifier`` and its mutations are no longer
|
||||||
|
tracked.
|
||||||
|
|
||||||
|
"""
|
||||||
r = self._backing_struct.pop(i)
|
r = self._backing_struct.pop(i)
|
||||||
if self.root.publish is not None:
|
if self.root.publish is not None:
|
||||||
self.root.publish(self.root, {"action": "pop",
|
self.root.publish(self.root, {"action": "pop",
|
||||||
|
@ -134,6 +194,14 @@ class Notifier:
|
||||||
|
|
||||||
|
|
||||||
class Publisher(AsyncioServer):
|
class Publisher(AsyncioServer):
|
||||||
|
"""A network server that publish changes to structures encapsulated in
|
||||||
|
``Notifiers``.
|
||||||
|
|
||||||
|
:param notifiers: A dictionary containing the notifiers to associate with
|
||||||
|
the ``Publisher``. The keys of the dictionary are the names of the
|
||||||
|
notifiers to be used with ``Subscriber``.
|
||||||
|
|
||||||
|
"""
|
||||||
def __init__(self, notifiers):
|
def __init__(self, notifiers):
|
||||||
AsyncioServer.__init__(self)
|
AsyncioServer.__init__(self)
|
||||||
self.notifiers = notifiers
|
self.notifiers = notifiers
|
||||||
|
|
|
@ -9,10 +9,10 @@ The most commonly used features from those modules can be imported with ``from a
|
||||||
.. automodule:: artiq.language.core
|
.. automodule:: artiq.language.core
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
:mod:`artiq.language.context` module
|
:mod:`artiq.language.db` module
|
||||||
------------------------------------
|
-------------------------------
|
||||||
|
|
||||||
.. automodule:: artiq.language.context
|
.. automodule:: artiq.language.db
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
:mod:`artiq.language.units` module
|
:mod:`artiq.language.units` module
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
Management reference
|
Management reference
|
||||||
====================
|
====================
|
||||||
|
|
||||||
|
:mod:`artiq.protocols.asyncio_server` module
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: artiq.protocols.asyncio_server
|
||||||
|
:members:
|
||||||
|
|
||||||
|
|
||||||
:mod:`artiq.protocols.pyon` module
|
:mod:`artiq.protocols.pyon` module
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
.. automodule:: artiq.protocols.pyon
|
.. automodule:: artiq.protocols.pyon
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
:mod:`artiq.protocols.tools` module
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
.. automodule:: artiq.protocols.tools
|
|
||||||
:members:
|
|
||||||
|
|
||||||
|
|
||||||
:mod:`artiq.protocols.pc_rpc` module
|
:mod:`artiq.protocols.pc_rpc` module
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue