supcon.intf module
This module contains the classes to describe interfaces on the supcon bus,
a base class Implementation
to implemet those interfaces and the
abstract class Node
which contains methods to interact with the
supcon bus.
# -*- coding: utf-8 -*- """ This module contains the classes to describe interfaces on the supcon bus, a base class `supcon.intf.Implementation` to implemet those interfaces and the abstract class `supcon.intf.Node` which contains methods to interact with the supcon bus. """ import re import abc import itertools import traceback import twisted.internet.defer as defer import supcon.util class Named(supcon.util.Named): """A base class for objects with a name. """ regex = None """re.RegexObject: a regular expression, the name must conform to""" def __init__(self, name): """Initializes the NamedAndDescribed instance Args: name (str): the name of the argument """ self.__name = self.toName(name) @property def name(self) -> str: """str: the name""" return self.__name @classmethod def toName(cls, value) -> str: """Converts the value into a name. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ value = str(value) if not cls.regex.fullmatch(value): raise ValueError("value {} must match {} fully".format(value, cls.regex.pattern)) return value class NamedAndDescribed(Named): """A base class for the interface describing classes `supcon.intf.Argument`, `supcon.intf.Event`, `supcon.intf.Method` and `supcon.intf.Interface` that all have the properties name and description.""" def __init__(self, name, description=''): """Initializes the NamedAndDescribed instance Args: name (str): the name of the argument description (str): a description of the argument """ Named.__init__(self, name) self.__description = self.toDescription(description) @property def description(self) -> str: """str: a description""" return self.__description @classmethod def toDescription(cls, value) -> str: """Converts the value into a description. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ return str(value) class DArgument(supcon.util.Dumpable, NamedAndDescribed): """Describes an input or output argument of a `supcon.intf.DMethod` or an argument of a `supcon.intf.DEvent`""" regex = re.compile('[a-zA-Z0-9]+') def validate(self, argument): """Validates the given argument value. Raises an ValueError if validation fails. """ pass def dump(self): data = {'name': self.name} if self.description != '': data['description'] = self.description return data @classmethod def load(cls, data): return cls(**data) class DArguments(supcon.util.NamedList): """A readonly map of `supcon.intf.DArgument` instances""" vtype = DArgument class DEvent(supcon.util.Dumpable, NamedAndDescribed): """Describes an event that can be emitted by an implementation on the bus""" regex = re.compile('[a-zA-Z0-9]+') def __init__(self, name, args=DArguments(), description=''): """Initializes the Event Args: name (str): the name of the event args (DArguments): the list of arguments of the event description (str): a description of the event """ NamedAndDescribed.__init__(self, name, description) self.__args = DArguments.to(args) @property def args(self) -> DArguments: """DArguments: the list of arguments of the event""" return self.__args def validateArgs(self, args): """Validates the given argument map. Raises an ValueError if validation fails. """ for arg in args: if arg not in self.__args: raise ValueError('event {} has no argument {}'.format(self.name, arg)) self.__args[arg].validate(args[arg]) for arg in self.__args: if arg not in args: raise ValueError('event {} needs argument {}'.format(self.name, arg)) def dump(self): data = {'name': self.name} if self.args: data['args'] = self.args.dump() if self.description != '': data['description'] = self.description return data @classmethod def load(cls, data): return cls(**data) class DEvents(supcon.util.NamedList): """A readonly map of `supcon.intf.DEvent` instances""" vtype = DEvent class DMethod(supcon.util.Dumpable, NamedAndDescribed): """A DMethod that can be called on an Object on the Bus""" regex = re.compile('[a-zA-Z0-9]+') def __init__(self, name, inArgs=DArguments(), outArgs=DArguments(), description=''): """Initializes the Event Args: name (str): the name of the method inArgs (DArguments): the list of input arguments of the method outArgs (DArguments): the list of output arguments of the method description (str): a description of the method """ NamedAndDescribed.__init__(self, name, description) self.__inArgs = DArguments.to(inArgs)# self.__outArgs = DArguments.to(outArgs) @property def inArgs(self) -> DArguments: """DArguments: The input arguments of the method""" return self.__inArgs @property def outArgs(self) -> DArguments: """DArguments: The output arguments of the method""" return self.__outArgs def validateInArgs(self, inArgs): """Validates the given argument Mapping. Raises an ValueError if validation fails """ for arg in inArgs: if arg not in self.__inArgs: raise ValueError('method {} has no input argument {}'.format(self.name, arg)) self.__inArgs[arg].validate(inArgs[arg]) for arg in self.__inArgs: if arg not in inArgs: raise ValueError('method {} needs input argument {}'.format(self.name, arg)) def validateOutArgs(self, outArgs): """Validates the given argument Mapping. Raises an ValueError if validation fails """ for arg in outArgs: if arg not in self.__outArgs: raise ValueError('method {} has no output argument {}'.format(self.name, arg)) self.__outArgs[arg].validate(outArgs[arg]) for arg in self.__outArgs: if arg not in outArgs: raise ValueError('method {} needs output argument {}'.format(self.name, arg)) def dump(self): data = {'name': self.name} if self.inArgs: data['inArgs'] = self.inArgs.dump() if self.outArgs: data['outArgs'] = self.outArgs.dump() if self.description != '': data['description'] = self.description return data @classmethod def load(cls, data): return cls(**data) class DMethods(supcon.util.NamedList): """A readonly map of `supcon.intf.DMethod` instances""" vtype = DMethod class DInterface(supcon.util.Dumpable, NamedAndDescribed): """An Interface that is implemented by an Object on the Bus""" regex = re.compile('([a-zA-Z0-9_]+\\.)*[a-zA-Z0-9_]+') def __init__(self, name, events=DEvents(), methods=DMethods(), description=''): """Initializes the Event Args: name (str): the name of the interface events (DEvents): the list of events of the interface methods (DMethods): the list of methods of the interface description (str): a description of the interface """ NamedAndDescribed.__init__(self, name, description) self.__events = DEvents.to(events) self.__methods = DMethods.to(methods) @property def events(self) -> DEvents: """DEvent: the list of events this interface can emit""" return self.__events @property def methods(self) -> DMethods: """DMethods: the list of methods this interface provides""" return self.__methods def validateEvent(self, event, args): """Validates that the given event is an event of this interface and that the given arguments are arguments of the event Args: event (str): the event args (dict): the arguments Raises: ValueError """ event = str(event) if event not in self.__events: raise ValueError('event {} is unknown'.format(event)) self.__events[event].validateArgs(args) def validateCall(self, method, inArgs): """Asserts that the given method is a method of this interface and that the given arguments are input arguments of the method Args: event (str): the event inArgs (dict): the input arguments Raises: AssertationError """ method = str(method) if method not in self.__methods: raise ValueError('method {} is unknown'.format(method)) self.__methods[method].validateInArgs(inArgs) def validateReturn(self, method, outArgs): """Asserts that the given method is a method of this interface and that the given arguments are output arguments of the method Args: event (str): the event outArgs (dict): the output arguments Raises: AssertationError """ method = str(method) if method not in self.__methods: raise ValueError('method {} is unknown'.format(method)) self.__methods[method].validateOutArgs(outArgs) def dump(self): data = {'name': self.name} if self.events: data['events'] = self.events.dump() if self.methods: data['methods'] = self.methods.dump() if self.description != '': data['description'] = self.description return data @classmethod def load(cls, data): return cls(**data) class DInterfaces(supcon.util.NamedList): """A readonly map of `supcon.intf.DInterface` instances""" vtype = DInterface class DPath(Named, supcon.util.NamedList): """A named readonly map of `supcon.intf.DInterface` instances""" vtype = DInterface regex = re.compile('/(([a-zA-Z0-9_]+/)*[a-zA-Z0-9_]+)?') def __init__(self, name, interfaces=None): """Initializes the Path instance Args: name (str): the name of the argument interfaces (): ... """ if interfaces is None: interfaces = [] Named.__init__(self, name) supcon.util.NamedList.__init__(self, interfaces) def dump(self): return { 'name': self.name, 'interfaces': [value.dump() for value in self.values()] } @classmethod def load(cls, data) -> 'DPath': return cls(**data) def addInterface(self, interface: DInterface) -> 'DPath': if interface.name in self: raise ValueError('interface {} at path {} already exists'.format(interface.name, self.name)) interfaces = itertools.chain(self.values(), [interface]) return DPath(self.name, interfaces) def delInterface(self, interface: DInterface) -> 'DPath': if interface.name not in self: raise ValueError('interface {} at path {} does not exist'.format(interface.name, self.name)) interfaces = (v for v in self.values() if v.name != interface.name) return DPath(self.name, interfaces) class DNode(Named, supcon.util.NamedList): """A named readonly map of `supcon.intf.DPath` instances""" vtype = DPath regex = re.compile('.+') def __init__(self, name, paths=None): """Initializes the Path instance Args: name (str): the name of the argument paths (): ... """ if paths is None: paths = [] Named.__init__(self, name) supcon.util.NamedList.__init__(self, paths) def dump(self): return { 'name': self.name, 'paths': [value.dump() for value in self.values()] } @classmethod def load(cls, data) -> 'DPath': return cls(**data) def hasPath(self, path: str) -> bool: return path in self def hasIntf(self, path: str, intf: str) -> bool: return path in self and intf in self[path] def addPath(self, path: str) -> 'DNode': if path in self: raise ValueError('path {} on node {} already exists'.format(path, self.name)) paths = itertools.chain(self.values(), [DPath(path)]) return DNode(self.name, paths) def delPath(self, path: str) -> 'DNode': if path not in self: raise ValueError('path {} on node {} does not exist'.format(path, self.name)) if self[path]: raise ValueError('path {} on node {} is not empty'.format(path, self.name)) paths = (v for v in self.values() if v.name != path) return DNode(self.name, paths) def addInterface(self, path: str, interface: DInterface) -> 'DNode': if path not in self: raise ValueError('path {} on node {} does not exist'.format(path, self.name)) if interface.name in self[path]: raise ValueError('interface {} at path {} on node {} already exists'.format(interface.name, path, self.name)) paths = (v for v in self.values() if v.name != path) paths = itertools.chain(paths, [self[path].addInterface(interface)]) return DNode(self.name, paths) def delInterface(self, path: str, interface: DInterface) -> 'DNode': if path not in self: raise ValueError('path {} on node {} does not exist'.format(path, self.name)) if interface.name not in self[path]: raise ValueError('interface {} at path {} on node {} does not exist'.format(interface.name, path, self.name)) paths = (v for v in self.values() if v.name != path) paths = itertools.chain(paths, [self[path].delInterface(interface)]) return DNode(self.name, paths) class DNodes(supcon.util.NamedList): """A readonly map of `supcon.intf.DNode` instances""" vtype = DNode def hasNode(self, node: str) -> bool: return node in self def hasPath(self, node: str, path: str) -> bool: return node in self and path in self[node] def hasIntf(self, node: str, path: str, intf: str) -> bool: return node in self and path in self[node] and intf in self[node][path] def addNode(self, node: str) -> 'DNodes': if node in self: raise ValueError('node {} already exists'.format(node)) nodes = itertools.chain(self.values(), [DNode(node)]) return DNodes(nodes) def delNode(self, node: str) -> 'DNodes': if node not in self: raise ValueError('node {} does not exist'.format(node)) if self[node]: raise ValueError('node {} is not empty'.format(node)) nodes = (v for v in self.values() if v.name != node) return DNodes(nodes) def addPath(self, node: str, path: str) -> 'DNodes': if node not in self: raise ValueError('node {} does not exist'.format(node)) nodes = (v for v in self.values() if v.name != node) nodes = itertools.chain(nodes, [self[node].addPath(path)]) return DNodes(nodes) def delPath(self, node: str, path: str) -> 'DNodes': if node not in self: raise ValueError('node {} does not exist'.format(node)) nodes = (v for v in self.values() if v.name != node) nodes = itertools.chain(nodes, [self[node].delPath(path)]) return DNodes(nodes) def addInterface(self, node: str, path: str, interface: DInterface) -> 'DNodes': if node not in self: raise ValueError('node {} does not exist'.format(node)) nodes = (v for v in self.values() if v.name != node) nodes = itertools.chain(nodes, [self[node].addInterface(path, interface)]) return DNodes(nodes) def delInterface(self, node: str, path: str, interface: DInterface) -> 'DNodes': if node not in self: raise ValueError('node {} does not exist'.format(node)) nodes = (v for v in self.values() if v.name != node) nodes = itertools.chain(nodes, [self[node].delInterface(path, interface)]) return DNodes(nodes) class Implementation(object): """The base class for interface implementations""" def __init__(self, interface: DInterface): """ Args: interface (DInterface): the interface that is implemented by this Implementation """ if not isinstance(interface, DInterface): raise ValueError('interface must be an instance of {}'.format(DInterface)) self.__interface = interface self.__callCbs = {} self.__fireCbs = [] @property def intf(self) -> str: """str: The name of the implemented interface""" return self.__interface.name @property def interface(self) -> DInterface: """Interface: The implemented interface""" return self.__interface def setCallCb(self, method: str, cb): """Sets a callback for the given method. The method must be a method of the interface this Implementation implements. The callback must implement the given method. The callback gets called by calls to Implementation.call() Args: method (str): the interface method that the callback implements cb (callable): the callback """ method = DMethod.toName(method) if method in self.__callCbs: raise ValueError('Callback for method {} is already set!'.format(method)) if method not in self.__interface.methods: raise ValueError('Interface has no method {}!'.format(method)) self.__callCbs[method] = cb def call(self, method: str, inArgs) -> defer.Deferred: """Calls the given interface method with the given arguments. This method calls the callback set by Implementation.setCallCb() Args: method (str): the called interface method inArgs (Mapping): a map of input arguments Returns: defer.Deferred: Resolves with the result of the called method """ def validateReturn(outArgs): self.__interface.validateReturn(method, outArgs) return outArgs try: self.__interface.validateCall(method, inArgs) if method not in self.__callCbs: raise ValueError('Callback for method {} is not set!'.format(method)) d = self.__callCbs[method](**inArgs) if not isinstance(d, defer.Deferred): d = defer.succeed(d) d.addCallback(validateReturn) except BaseException as e: traceback.print_exc() d = defer.fail(e) return d def addFireCb(self, cb): """Adds a callback that gets called, when this Implementation fires an event. Args: cb (callable): the callback """ self.__fireCbs.append(cb) def delFireCb(self, cb): """Removes a callback that gets called, when this Implementation fires an event. Args: cb (callable): the callback """ self.__fireCbs.remove(cb) def fire(self, event: str, args): """Fires the given event with the given arguments. Args: event (str): the event name args (collecion.Mapping): the event arguments """ self.__interface.validateEvent(event, args) for cb in self.__fireCbs: cb(event, args) class Object(object): def __init__(self, interfaces=None): """ Args: interfaces (DInterfaces): the interfaces that are implemented by this Object """ if interfaces is None: interfaces = [] self.__intfs = {} self.__impls = {} def getCallCb(intf): return lambda method, inArgs: self.__call(intf, method, inArgs) for interface in interfaces: if not isinstance(interface, DInterface): raise ValueError('interface must be an instance of {}'.format(DInterface)) self.__intfs[interface.name] = interface implementation = Implementation(interface) callCb = getCallCb(implementation.intf) for method in interface.methods: implementation.setCallCb(method, callCb) self.__impls[implementation.intf] = implementation @property def interfaces(self): return self.__intfs.values() @property def implementations(self): return self.__impls.values() def interface(self, intf): return self.__intfs[intf] def implementation(self, intf): return self.__impls[intf] def __call(self, intf: str, method: str, inArgs) -> defer.Deferred: pass class Node(abc.ABC): """The Node Interface. This class defines the methods that participants can use to access the supcon bus.""" def __init__(self, name): super().__init__() self.__name = self.toName(name) @property def name(self) -> str: """str: The name of the node on the bus""" return self.__name @classmethod def toName(cls, value) -> str: return DNode.toName(value) @abc.abstractmethod def nodes(self) -> DNodes: """list[str]: The currently connected nodes""" raise NotImplementedError() @abc.abstractmethod def connect(self, endpoint): """Connects the node to the given endpoint. If the connection failes or closes the connection gets reestablished with an exponential timeout up to two minutes. Args: endpoint (twisted.internet.interfaces.IStreamClientEndpoint): """ raise NotImplementedError() @abc.abstractmethod def listen(self, endpoint): """Listens at the given endpoint for incoming connections Args: endpoint (twisted.internet.interfaces.IStreamServerEndpoint): """ raise NotImplementedError() @abc.abstractmethod def register(self, path: str, impl: Implementation): """Registers an implementation with the node Args: impl (Implementation): """ raise NotImplementedError() @abc.abstractmethod def unregister(self, path: str, impl: Implementation): """Removes an implementation from the node Args: impl (supcon.intf.Implementation): """ raise NotImplementedError() @abc.abstractmethod def call(self, node: str, path: str, intf: str, method: str, args: dict) -> defer.Deferred: """Calls a method on the bus Args: node (str): a node on the bus path (str): a path on the given node intf (str): an interface at the given path method (str): a method of the given interface args (dict): a dict of method arguments Returns: defer.Deferred: """ raise NotImplementedError() @abc.abstractmethod def on(self, node: str, path: str, intf: str, event: str, cb): """Registers a callback for an event on the bus Args: node (str): a node on the bus path (str): a path on the given node intf (str): an interface at the given path event (str): a method of the given interface cb (callable): a callable that gets called with a dict of event arguments """ raise NotImplementedError() @abc.abstractmethod def off(self, node: str, path: str, intf: str, event: str, cb): """Unregisters a callback for an event on the bus Args: node (str): a node on the bus path (str): a path on the given node intf (str): an interface at the given path event (str): a method of the given interface cb (callable): a callable that gets called with a dict of event arguments """ raise NotImplementedError()
Classes
class DArgument
class DArgument(supcon.util.Dumpable, NamedAndDescribed): """Describes an input or output argument of a `supcon.intf.DMethod` or an argument of a `supcon.intf.DEvent`""" regex = re.compile('[a-zA-Z0-9]+') def validate(self, argument): """Validates the given argument value. Raises an ValueError if validation fails. """ pass def dump(self): data = {'name': self.name} if self.description != '': data['description'] = self.description return data @classmethod def load(cls, data): return cls(**data)
Ancestors (in MRO)
- DArgument
- supcon.util.Dumpable
- NamedAndDescribed
- Named
- supcon.util.Named
- abc.ABC
- builtins.object
Class variables
var regex
Class Methods
def load(
cls, data)
@classmethod def load(cls, data): return cls(**data)
def toDescription(
cls, value)
Converts the value into a description. If this is impossible a ValueError is raised.
Args: value (any): the value Raises: ValueError
@classmethod def toDescription(cls, value) -> str: """Converts the value into a description. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ return str(value)
def toName(
cls, value)
Converts the value into a name. If this is impossible a ValueError is raised.
Args: value (any): the value Raises: ValueError
@classmethod def toName(cls, value) -> str: """Converts the value into a name. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ value = str(value) if not cls.regex.fullmatch(value): raise ValueError("value {} must match {} fully".format(value, cls.regex.pattern)) return value
Instance variables
Methods
def __init__(
self, name, description='')
Initializes the NamedAndDescribed instance
Args: name (str): the name of the argument description (str): a description of the argument
def __init__(self, name, description=''): """Initializes the NamedAndDescribed instance Args: name (str): the name of the argument description (str): a description of the argument """ Named.__init__(self, name) self.__description = self.toDescription(description)
def dump(
self)
Converts the supcon.util.Dumpable
into a 'simple' datastructure.
def dump(self): data = {'name': self.name} if self.description != '': data['description'] = self.description return data
def validate(
self, argument)
Validates the given argument value. Raises an ValueError if validation fails.
def validate(self, argument): """Validates the given argument value. Raises an ValueError if validation fails. """ pass
class DArguments
A readonly map of DArgument
instances
class DArguments(supcon.util.NamedList): """A readonly map of `supcon.intf.DArgument` instances""" vtype = DArgument
Ancestors (in MRO)
- DArguments
- supcon.util.NamedList
- collections.abc.Mapping
- collections.abc.Collection
- collections.abc.Sized
- collections.abc.Iterable
- collections.abc.Container
- supcon.util.Dumpable
- abc.ABC
- builtins.object
Class variables
var vtype
Class Methods
def load(
cls, data)
Converts the given list of 'simple' datastructures data into an instance
of cls, a subclass of supcon.util.NamedList
.
@classmethod def load(cls, data): """ Converts the given list of 'simple' datastructures **data** into an instance of **cls**, a subclass of `supcon.util.NamedList`. """ return cls(data)
def to(
cls, value)
If the the value is an instance of cls, a subclass of
supcon.util.NamedList
, the value is returned. If value is not an instance
of cls the method tries to convert the value into an instance of
cls.
@classmethod def to(cls, value): """ If the the **value** is an instance of **cls**, a subclass of `supcon.util.NamedList`, the value is returned. If value is not an instance of **cls** the method tries to convert the **value** into an instance of **cls**. """ return value if isinstance(value, cls) else cls.load(value)
Methods
def __init__(
self, values=None)
Initializes the supcon.util.NamedList
with the given list of values.
An element of values must be of type supcon.util.NamedList.vtype
or a
'simple' datastructure that can be converted to an instance of
supcon.util.NamedList.vtype
by supcon.util.NamedList.vtype
.load().
def __init__(self, values=None): """ Initializes the `supcon.util.NamedList` with the given list of **values**. An element of **values** must be of type `supcon.util.NamedList.vtype` or a 'simple' datastructure that can be converted to an instance of `supcon.util.NamedList.vtype` by `supcon.util.NamedList.vtype`.load(). """ if values is None: values = [] if not issubclass(self.vtype, Named): raise ValueError('the value type must be a subclass of Named') if not issubclass(self.vtype, Dumpable): raise ValueError('the value type must be a subclass of Dumpable') self.__values = collections.OrderedDict() for value in values: if not isinstance(value, self.vtype): value = self.vtype.load(value) if value.name in self.__values: raise ValueError('value.name must be unique in the given list of values') self.__values[value.name] = value
def dump(
self)
Converts the supcon.util.NamedList
into a list of 'simple' datastructures.
def dump(self): """ Converts the `supcon.util.NamedList` into a list of 'simple' datastructures. """ return [value.dump() for value in self.values()]
def get(
self, key, default=None)
D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.
def get(self, key, default=None): 'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.' try: return self[key] except KeyError: return default
def items(
self)
D.items() -> a set-like object providing a view on D's items
def items(self): "D.items() -> a set-like object providing a view on D's items" return ItemsView(self)
def keys(
self)
D.keys() -> a set-like object providing a view on D's keys
def keys(self): "D.keys() -> a set-like object providing a view on D's keys" return KeysView(self)
def values(
self)
D.values() -> an object providing a view on D's values
def values(self): "D.values() -> an object providing a view on D's values" return ValuesView(self)
class DEvent
Describes an event that can be emitted by an implementation on the bus
class DEvent(supcon.util.Dumpable, NamedAndDescribed): """Describes an event that can be emitted by an implementation on the bus""" regex = re.compile('[a-zA-Z0-9]+') def __init__(self, name, args=DArguments(), description=''): """Initializes the Event Args: name (str): the name of the event args (DArguments): the list of arguments of the event description (str): a description of the event """ NamedAndDescribed.__init__(self, name, description) self.__args = DArguments.to(args) @property def args(self) -> DArguments: """DArguments: the list of arguments of the event""" return self.__args def validateArgs(self, args): """Validates the given argument map. Raises an ValueError if validation fails. """ for arg in args: if arg not in self.__args: raise ValueError('event {} has no argument {}'.format(self.name, arg)) self.__args[arg].validate(args[arg]) for arg in self.__args: if arg not in args: raise ValueError('event {} needs argument {}'.format(self.name, arg)) def dump(self): data = {'name': self.name} if self.args: data['args'] = self.args.dump() if self.description != '': data['description'] = self.description return data @classmethod def load(cls, data): return cls(**data)
Ancestors (in MRO)
- DEvent
- supcon.util.Dumpable
- NamedAndDescribed
- Named
- supcon.util.Named
- abc.ABC
- builtins.object
Class variables
var regex
Class Methods
def load(
cls, data)
@classmethod def load(cls, data): return cls(**data)
def toDescription(
cls, value)
Converts the value into a description. If this is impossible a ValueError is raised.
Args: value (any): the value Raises: ValueError
@classmethod def toDescription(cls, value) -> str: """Converts the value into a description. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ return str(value)
def toName(
cls, value)
Converts the value into a name. If this is impossible a ValueError is raised.
Args: value (any): the value Raises: ValueError
@classmethod def toName(cls, value) -> str: """Converts the value into a name. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ value = str(value) if not cls.regex.fullmatch(value): raise ValueError("value {} must match {} fully".format(value, cls.regex.pattern)) return value
Instance variables
var args
DArguments: the list of arguments of the event
var description
str: a description
var name
str: the name
Methods
def __init__(
self, name, args=supcon.intf.DArguments(), description='')
Initializes the Event
Args: name (str): the name of the event args (DArguments): the list of arguments of the event description (str): a description of the event
def __init__(self, name, args=DArguments(), description=''): """Initializes the Event Args: name (str): the name of the event args (DArguments): the list of arguments of the event description (str): a description of the event """ NamedAndDescribed.__init__(self, name, description) self.__args = DArguments.to(args)
def dump(
self)
Converts the supcon.util.Dumpable
into a 'simple' datastructure.
def dump(self): data = {'name': self.name} if self.args: data['args'] = self.args.dump() if self.description != '': data['description'] = self.description return data
def validateArgs(
self, args)
Validates the given argument map. Raises an ValueError if validation fails.
def validateArgs(self, args): """Validates the given argument map. Raises an ValueError if validation fails. """ for arg in args: if arg not in self.__args: raise ValueError('event {} has no argument {}'.format(self.name, arg)) self.__args[arg].validate(args[arg]) for arg in self.__args: if arg not in args: raise ValueError('event {} needs argument {}'.format(self.name, arg))
class DEvents
A readonly map of DEvent
instances
class DEvents(supcon.util.NamedList): """A readonly map of `supcon.intf.DEvent` instances""" vtype = DEvent
Ancestors (in MRO)
- DEvents
- supcon.util.NamedList
- collections.abc.Mapping
- collections.abc.Collection
- collections.abc.Sized
- collections.abc.Iterable
- collections.abc.Container
- supcon.util.Dumpable
- abc.ABC
- builtins.object
Class variables
var vtype
Class Methods
def load(
cls, data)
Converts the given list of 'simple' datastructures data into an instance
of cls, a subclass of supcon.util.NamedList
.
@classmethod def load(cls, data): """ Converts the given list of 'simple' datastructures **data** into an instance of **cls**, a subclass of `supcon.util.NamedList`. """ return cls(data)
def to(
cls, value)
If the the value is an instance of cls, a subclass of
supcon.util.NamedList
, the value is returned. If value is not an instance
of cls the method tries to convert the value into an instance of
cls.
@classmethod def to(cls, value): """ If the the **value** is an instance of **cls**, a subclass of `supcon.util.NamedList`, the value is returned. If value is not an instance of **cls** the method tries to convert the **value** into an instance of **cls**. """ return value if isinstance(value, cls) else cls.load(value)
Methods
def __init__(
self, values=None)
Initializes the supcon.util.NamedList
with the given list of values.
An element of values must be of type supcon.util.NamedList.vtype
or a
'simple' datastructure that can be converted to an instance of
supcon.util.NamedList.vtype
by supcon.util.NamedList.vtype
.load().
def __init__(self, values=None): """ Initializes the `supcon.util.NamedList` with the given list of **values**. An element of **values** must be of type `supcon.util.NamedList.vtype` or a 'simple' datastructure that can be converted to an instance of `supcon.util.NamedList.vtype` by `supcon.util.NamedList.vtype`.load(). """ if values is None: values = [] if not issubclass(self.vtype, Named): raise ValueError('the value type must be a subclass of Named') if not issubclass(self.vtype, Dumpable): raise ValueError('the value type must be a subclass of Dumpable') self.__values = collections.OrderedDict() for value in values: if not isinstance(value, self.vtype): value = self.vtype.load(value) if value.name in self.__values: raise ValueError('value.name must be unique in the given list of values') self.__values[value.name] = value
def dump(
self)
Converts the supcon.util.NamedList
into a list of 'simple' datastructures.
def dump(self): """ Converts the `supcon.util.NamedList` into a list of 'simple' datastructures. """ return [value.dump() for value in self.values()]
def get(
self, key, default=None)
D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.
def get(self, key, default=None): 'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.' try: return self[key] except KeyError: return default
def items(
self)
D.items() -> a set-like object providing a view on D's items
def items(self): "D.items() -> a set-like object providing a view on D's items" return ItemsView(self)
def keys(
self)
D.keys() -> a set-like object providing a view on D's keys
def keys(self): "D.keys() -> a set-like object providing a view on D's keys" return KeysView(self)
def values(
self)
D.values() -> an object providing a view on D's values
def values(self): "D.values() -> an object providing a view on D's values" return ValuesView(self)
class DInterface
An Interface that is implemented by an Object on the Bus
class DInterface(supcon.util.Dumpable, NamedAndDescribed): """An Interface that is implemented by an Object on the Bus""" regex = re.compile('([a-zA-Z0-9_]+\\.)*[a-zA-Z0-9_]+') def __init__(self, name, events=DEvents(), methods=DMethods(), description=''): """Initializes the Event Args: name (str): the name of the interface events (DEvents): the list of events of the interface methods (DMethods): the list of methods of the interface description (str): a description of the interface """ NamedAndDescribed.__init__(self, name, description) self.__events = DEvents.to(events) self.__methods = DMethods.to(methods) @property def events(self) -> DEvents: """DEvent: the list of events this interface can emit""" return self.__events @property def methods(self) -> DMethods: """DMethods: the list of methods this interface provides""" return self.__methods def validateEvent(self, event, args): """Validates that the given event is an event of this interface and that the given arguments are arguments of the event Args: event (str): the event args (dict): the arguments Raises: ValueError """ event = str(event) if event not in self.__events: raise ValueError('event {} is unknown'.format(event)) self.__events[event].validateArgs(args) def validateCall(self, method, inArgs): """Asserts that the given method is a method of this interface and that the given arguments are input arguments of the method Args: event (str): the event inArgs (dict): the input arguments Raises: AssertationError """ method = str(method) if method not in self.__methods: raise ValueError('method {} is unknown'.format(method)) self.__methods[method].validateInArgs(inArgs) def validateReturn(self, method, outArgs): """Asserts that the given method is a method of this interface and that the given arguments are output arguments of the method Args: event (str): the event outArgs (dict): the output arguments Raises: AssertationError """ method = str(method) if method not in self.__methods: raise ValueError('method {} is unknown'.format(method)) self.__methods[method].validateOutArgs(outArgs) def dump(self): data = {'name': self.name} if self.events: data['events'] = self.events.dump() if self.methods: data['methods'] = self.methods.dump() if self.description != '': data['description'] = self.description return data @classmethod def load(cls, data): return cls(**data)
Ancestors (in MRO)
- DInterface
- supcon.util.Dumpable
- NamedAndDescribed
- Named
- supcon.util.Named
- abc.ABC
- builtins.object
Class variables
var regex
Class Methods
def load(
cls, data)
@classmethod def load(cls, data): return cls(**data)
def toDescription(
cls, value)
Converts the value into a description. If this is impossible a ValueError is raised.
Args: value (any): the value Raises: ValueError
@classmethod def toDescription(cls, value) -> str: """Converts the value into a description. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ return str(value)
def toName(
cls, value)
Converts the value into a name. If this is impossible a ValueError is raised.
Args: value (any): the value Raises: ValueError
@classmethod def toName(cls, value) -> str: """Converts the value into a name. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ value = str(value) if not cls.regex.fullmatch(value): raise ValueError("value {} must match {} fully".format(value, cls.regex.pattern)) return value
Instance variables
var events
DEvent: the list of events this interface can emit
var methods
DMethods: the list of methods this interface provides
var name
str: the name
Methods
def __init__(
self, name, events=supcon.intf.DEvents(), methods=supcon.intf.DMethods(), description='')
Initializes the Event
Args: name (str): the name of the interface events (DEvents): the list of events of the interface methods (DMethods): the list of methods of the interface description (str): a description of the interface
def __init__(self, name, events=DEvents(), methods=DMethods(), description=''): """Initializes the Event Args: name (str): the name of the interface events (DEvents): the list of events of the interface methods (DMethods): the list of methods of the interface description (str): a description of the interface """ NamedAndDescribed.__init__(self, name, description) self.__events = DEvents.to(events) self.__methods = DMethods.to(methods)
def dump(
self)
Converts the supcon.util.Dumpable
into a 'simple' datastructure.
def dump(self): data = {'name': self.name} if self.events: data['events'] = self.events.dump() if self.methods: data['methods'] = self.methods.dump() if self.description != '': data['description'] = self.description return data
def validateCall(
self, method, inArgs)
Asserts that the given method is a method of this interface and that the given arguments are input arguments of the method
Args: event (str): the event inArgs (dict): the input arguments Raises: AssertationError
def validateCall(self, method, inArgs): """Asserts that the given method is a method of this interface and that the given arguments are input arguments of the method Args: event (str): the event inArgs (dict): the input arguments Raises: AssertationError """ method = str(method) if method not in self.__methods: raise ValueError('method {} is unknown'.format(method)) self.__methods[method].validateInArgs(inArgs)
def validateEvent(
self, event, args)
Validates that the given event is an event of this interface and that the given arguments are arguments of the event
Args: event (str): the event args (dict): the arguments Raises: ValueError
def validateEvent(self, event, args): """Validates that the given event is an event of this interface and that the given arguments are arguments of the event Args: event (str): the event args (dict): the arguments Raises: ValueError """ event = str(event) if event not in self.__events: raise ValueError('event {} is unknown'.format(event)) self.__events[event].validateArgs(args)
def validateReturn(
self, method, outArgs)
Asserts that the given method is a method of this interface and that the given arguments are output arguments of the method
Args: event (str): the event outArgs (dict): the output arguments Raises: AssertationError
def validateReturn(self, method, outArgs): """Asserts that the given method is a method of this interface and that the given arguments are output arguments of the method Args: event (str): the event outArgs (dict): the output arguments Raises: AssertationError """ method = str(method) if method not in self.__methods: raise ValueError('method {} is unknown'.format(method)) self.__methods[method].validateOutArgs(outArgs)
class DInterfaces
A readonly map of DInterface
instances
class DInterfaces(supcon.util.NamedList): """A readonly map of `supcon.intf.DInterface` instances""" vtype = DInterface
Ancestors (in MRO)
- DInterfaces
- supcon.util.NamedList
- collections.abc.Mapping
- collections.abc.Collection
- collections.abc.Sized
- collections.abc.Iterable
- collections.abc.Container
- supcon.util.Dumpable
- abc.ABC
- builtins.object
Class variables
var vtype
Class Methods
def load(
cls, data)
Converts the given list of 'simple' datastructures data into an instance
of cls, a subclass of supcon.util.NamedList
.
@classmethod def load(cls, data): """ Converts the given list of 'simple' datastructures **data** into an instance of **cls**, a subclass of `supcon.util.NamedList`. """ return cls(data)
def to(
cls, value)
If the the value is an instance of cls, a subclass of
supcon.util.NamedList
, the value is returned. If value is not an instance
of cls the method tries to convert the value into an instance of
cls.
@classmethod def to(cls, value): """ If the the **value** is an instance of **cls**, a subclass of `supcon.util.NamedList`, the value is returned. If value is not an instance of **cls** the method tries to convert the **value** into an instance of **cls**. """ return value if isinstance(value, cls) else cls.load(value)
Methods
def __init__(
self, values=None)
Initializes the supcon.util.NamedList
with the given list of values.
An element of values must be of type supcon.util.NamedList.vtype
or a
'simple' datastructure that can be converted to an instance of
supcon.util.NamedList.vtype
by supcon.util.NamedList.vtype
.load().
def __init__(self, values=None): """ Initializes the `supcon.util.NamedList` with the given list of **values**. An element of **values** must be of type `supcon.util.NamedList.vtype` or a 'simple' datastructure that can be converted to an instance of `supcon.util.NamedList.vtype` by `supcon.util.NamedList.vtype`.load(). """ if values is None: values = [] if not issubclass(self.vtype, Named): raise ValueError('the value type must be a subclass of Named') if not issubclass(self.vtype, Dumpable): raise ValueError('the value type must be a subclass of Dumpable') self.__values = collections.OrderedDict() for value in values: if not isinstance(value, self.vtype): value = self.vtype.load(value) if value.name in self.__values: raise ValueError('value.name must be unique in the given list of values') self.__values[value.name] = value
def dump(
self)
Converts the supcon.util.NamedList
into a list of 'simple' datastructures.
def dump(self): """ Converts the `supcon.util.NamedList` into a list of 'simple' datastructures. """ return [value.dump() for value in self.values()]
def get(
self, key, default=None)
D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.
def get(self, key, default=None): 'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.' try: return self[key] except KeyError: return default
def items(
self)
D.items() -> a set-like object providing a view on D's items
def items(self): "D.items() -> a set-like object providing a view on D's items" return ItemsView(self)
def keys(
self)
D.keys() -> a set-like object providing a view on D's keys
def keys(self): "D.keys() -> a set-like object providing a view on D's keys" return KeysView(self)
def values(
self)
D.values() -> an object providing a view on D's values
def values(self): "D.values() -> an object providing a view on D's values" return ValuesView(self)
class DMethod
A DMethod that can be called on an Object on the Bus
class DMethod(supcon.util.Dumpable, NamedAndDescribed): """A DMethod that can be called on an Object on the Bus""" regex = re.compile('[a-zA-Z0-9]+') def __init__(self, name, inArgs=DArguments(), outArgs=DArguments(), description=''): """Initializes the Event Args: name (str): the name of the method inArgs (DArguments): the list of input arguments of the method outArgs (DArguments): the list of output arguments of the method description (str): a description of the method """ NamedAndDescribed.__init__(self, name, description) self.__inArgs = DArguments.to(inArgs)# self.__outArgs = DArguments.to(outArgs) @property def inArgs(self) -> DArguments: """DArguments: The input arguments of the method""" return self.__inArgs @property def outArgs(self) -> DArguments: """DArguments: The output arguments of the method""" return self.__outArgs def validateInArgs(self, inArgs): """Validates the given argument Mapping. Raises an ValueError if validation fails """ for arg in inArgs: if arg not in self.__inArgs: raise ValueError('method {} has no input argument {}'.format(self.name, arg)) self.__inArgs[arg].validate(inArgs[arg]) for arg in self.__inArgs: if arg not in inArgs: raise ValueError('method {} needs input argument {}'.format(self.name, arg)) def validateOutArgs(self, outArgs): """Validates the given argument Mapping. Raises an ValueError if validation fails """ for arg in outArgs: if arg not in self.__outArgs: raise ValueError('method {} has no output argument {}'.format(self.name, arg)) self.__outArgs[arg].validate(outArgs[arg]) for arg in self.__outArgs: if arg not in outArgs: raise ValueError('method {} needs output argument {}'.format(self.name, arg)) def dump(self): data = {'name': self.name} if self.inArgs: data['inArgs'] = self.inArgs.dump() if self.outArgs: data['outArgs'] = self.outArgs.dump() if self.description != '': data['description'] = self.description return data @classmethod def load(cls, data): return cls(**data)
Ancestors (in MRO)
- DMethod
- supcon.util.Dumpable
- NamedAndDescribed
- Named
- supcon.util.Named
- abc.ABC
- builtins.object
Class variables
var regex
Class Methods
def load(
cls, data)
@classmethod def load(cls, data): return cls(**data)
def toDescription(
cls, value)
Converts the value into a description. If this is impossible a ValueError is raised.
Args: value (any): the value Raises: ValueError
@classmethod def toDescription(cls, value) -> str: """Converts the value into a description. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ return str(value)
def toName(
cls, value)
Converts the value into a name. If this is impossible a ValueError is raised.
Args: value (any): the value Raises: ValueError
@classmethod def toName(cls, value) -> str: """Converts the value into a name. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ value = str(value) if not cls.regex.fullmatch(value): raise ValueError("value {} must match {} fully".format(value, cls.regex.pattern)) return value
Instance variables
var inArgs
DArguments: The input arguments of the method
var name
str: the name
var outArgs
DArguments: The output arguments of the method
Methods
def __init__(
self, name, inArgs=supcon.intf.DArguments(), outArgs=supcon.intf.DArguments(), description='')
Initializes the Event
Args: name (str): the name of the method inArgs (DArguments): the list of input arguments of the method outArgs (DArguments): the list of output arguments of the method description (str): a description of the method
def __init__(self, name, inArgs=DArguments(), outArgs=DArguments(), description=''): """Initializes the Event Args: name (str): the name of the method inArgs (DArguments): the list of input arguments of the method outArgs (DArguments): the list of output arguments of the method description (str): a description of the method """ NamedAndDescribed.__init__(self, name, description) self.__inArgs = DArguments.to(inArgs)# self.__outArgs = DArguments.to(outArgs)
def dump(
self)
Converts the supcon.util.Dumpable
into a 'simple' datastructure.
def dump(self): data = {'name': self.name} if self.inArgs: data['inArgs'] = self.inArgs.dump() if self.outArgs: data['outArgs'] = self.outArgs.dump() if self.description != '': data['description'] = self.description return data
def validateInArgs(
self, inArgs)
Validates the given argument Mapping. Raises an ValueError if validation fails
def validateInArgs(self, inArgs): """Validates the given argument Mapping. Raises an ValueError if validation fails """ for arg in inArgs: if arg not in self.__inArgs: raise ValueError('method {} has no input argument {}'.format(self.name, arg)) self.__inArgs[arg].validate(inArgs[arg]) for arg in self.__inArgs: if arg not in inArgs: raise ValueError('method {} needs input argument {}'.format(self.name, arg))
def validateOutArgs(
self, outArgs)
Validates the given argument Mapping. Raises an ValueError if validation fails
def validateOutArgs(self, outArgs): """Validates the given argument Mapping. Raises an ValueError if validation fails """ for arg in outArgs: if arg not in self.__outArgs: raise ValueError('method {} has no output argument {}'.format(self.name, arg)) self.__outArgs[arg].validate(outArgs[arg]) for arg in self.__outArgs: if arg not in outArgs: raise ValueError('method {} needs output argument {}'.format(self.name, arg))
class DMethods
A readonly map of DMethod
instances
class DMethods(supcon.util.NamedList): """A readonly map of `supcon.intf.DMethod` instances""" vtype = DMethod
Ancestors (in MRO)
- DMethods
- supcon.util.NamedList
- collections.abc.Mapping
- collections.abc.Collection
- collections.abc.Sized
- collections.abc.Iterable
- collections.abc.Container
- supcon.util.Dumpable
- abc.ABC
- builtins.object
Class variables
var vtype
Class Methods
def load(
cls, data)
Converts the given list of 'simple' datastructures data into an instance
of cls, a subclass of supcon.util.NamedList
.
@classmethod def load(cls, data): """ Converts the given list of 'simple' datastructures **data** into an instance of **cls**, a subclass of `supcon.util.NamedList`. """ return cls(data)
def to(
cls, value)
If the the value is an instance of cls, a subclass of
supcon.util.NamedList
, the value is returned. If value is not an instance
of cls the method tries to convert the value into an instance of
cls.
@classmethod def to(cls, value): """ If the the **value** is an instance of **cls**, a subclass of `supcon.util.NamedList`, the value is returned. If value is not an instance of **cls** the method tries to convert the **value** into an instance of **cls**. """ return value if isinstance(value, cls) else cls.load(value)
Methods
def __init__(
self, values=None)
Initializes the supcon.util.NamedList
with the given list of values.
An element of values must be of type supcon.util.NamedList.vtype
or a
'simple' datastructure that can be converted to an instance of
supcon.util.NamedList.vtype
by supcon.util.NamedList.vtype
.load().
def __init__(self, values=None): """ Initializes the `supcon.util.NamedList` with the given list of **values**. An element of **values** must be of type `supcon.util.NamedList.vtype` or a 'simple' datastructure that can be converted to an instance of `supcon.util.NamedList.vtype` by `supcon.util.NamedList.vtype`.load(). """ if values is None: values = [] if not issubclass(self.vtype, Named): raise ValueError('the value type must be a subclass of Named') if not issubclass(self.vtype, Dumpable): raise ValueError('the value type must be a subclass of Dumpable') self.__values = collections.OrderedDict() for value in values: if not isinstance(value, self.vtype): value = self.vtype.load(value) if value.name in self.__values: raise ValueError('value.name must be unique in the given list of values') self.__values[value.name] = value
def dump(
self)
Converts the supcon.util.NamedList
into a list of 'simple' datastructures.
def dump(self): """ Converts the `supcon.util.NamedList` into a list of 'simple' datastructures. """ return [value.dump() for value in self.values()]
def get(
self, key, default=None)
D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.
def get(self, key, default=None): 'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.' try: return self[key] except KeyError: return default
def items(
self)
D.items() -> a set-like object providing a view on D's items
def items(self): "D.items() -> a set-like object providing a view on D's items" return ItemsView(self)
def keys(
self)
D.keys() -> a set-like object providing a view on D's keys
def keys(self): "D.keys() -> a set-like object providing a view on D's keys" return KeysView(self)
def values(
self)
D.values() -> an object providing a view on D's values
def values(self): "D.values() -> an object providing a view on D's values" return ValuesView(self)
class DNode
A named readonly map of DPath
instances
class DNode(Named, supcon.util.NamedList): """A named readonly map of `supcon.intf.DPath` instances""" vtype = DPath regex = re.compile('.+') def __init__(self, name, paths=None): """Initializes the Path instance Args: name (str): the name of the argument paths (): ... """ if paths is None: paths = [] Named.__init__(self, name) supcon.util.NamedList.__init__(self, paths) def dump(self): return { 'name': self.name, 'paths': [value.dump() for value in self.values()] } @classmethod def load(cls, data) -> 'DPath': return cls(**data) def hasPath(self, path: str) -> bool: return path in self def hasIntf(self, path: str, intf: str) -> bool: return path in self and intf in self[path] def addPath(self, path: str) -> 'DNode': if path in self: raise ValueError('path {} on node {} already exists'.format(path, self.name)) paths = itertools.chain(self.values(), [DPath(path)]) return DNode(self.name, paths) def delPath(self, path: str) -> 'DNode': if path not in self: raise ValueError('path {} on node {} does not exist'.format(path, self.name)) if self[path]: raise ValueError('path {} on node {} is not empty'.format(path, self.name)) paths = (v for v in self.values() if v.name != path) return DNode(self.name, paths) def addInterface(self, path: str, interface: DInterface) -> 'DNode': if path not in self: raise ValueError('path {} on node {} does not exist'.format(path, self.name)) if interface.name in self[path]: raise ValueError('interface {} at path {} on node {} already exists'.format(interface.name, path, self.name)) paths = (v for v in self.values() if v.name != path) paths = itertools.chain(paths, [self[path].addInterface(interface)]) return DNode(self.name, paths) def delInterface(self, path: str, interface: DInterface) -> 'DNode': if path not in self: raise ValueError('path {} on node {} does not exist'.format(path, self.name)) if interface.name not in self[path]: raise ValueError('interface {} at path {} on node {} does not exist'.format(interface.name, path, self.name)) paths = (v for v in self.values() if v.name != path) paths = itertools.chain(paths, [self[path].delInterface(interface)]) return DNode(self.name, paths)
Ancestors (in MRO)
- DNode
- Named
- supcon.util.Named
- supcon.util.NamedList
- collections.abc.Mapping
- collections.abc.Collection
- collections.abc.Sized
- collections.abc.Iterable
- collections.abc.Container
- supcon.util.Dumpable
- abc.ABC
- builtins.object
Class variables
var regex
var vtype
Class Methods
def load(
cls, data)
@classmethod def load(cls, data) -> 'DPath': return cls(**data)
def to(
cls, value)
If the the value is an instance of cls, a subclass of
supcon.util.NamedList
, the value is returned. If value is not an instance
of cls the method tries to convert the value into an instance of
cls.
@classmethod def to(cls, value): """ If the the **value** is an instance of **cls**, a subclass of `supcon.util.NamedList`, the value is returned. If value is not an instance of **cls** the method tries to convert the **value** into an instance of **cls**. """ return value if isinstance(value, cls) else cls.load(value)
def toName(
cls, value)
Converts the value into a name. If this is impossible a ValueError is raised.
Args: value (any): the value Raises: ValueError
@classmethod def toName(cls, value) -> str: """Converts the value into a name. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ value = str(value) if not cls.regex.fullmatch(value): raise ValueError("value {} must match {} fully".format(value, cls.regex.pattern)) return value
Instance variables
Methods
def __init__(
self, name, paths=None)
Initializes the Path instance
Args: name (str): the name of the argument paths (): ...
def __init__(self, name, paths=None): """Initializes the Path instance Args: name (str): the name of the argument paths (): ... """ if paths is None: paths = [] Named.__init__(self, name) supcon.util.NamedList.__init__(self, paths)
def addInterface(
self, path, interface)
def addInterface(self, path: str, interface: DInterface) -> 'DNode': if path not in self: raise ValueError('path {} on node {} does not exist'.format(path, self.name)) if interface.name in self[path]: raise ValueError('interface {} at path {} on node {} already exists'.format(interface.name, path, self.name)) paths = (v for v in self.values() if v.name != path) paths = itertools.chain(paths, [self[path].addInterface(interface)]) return DNode(self.name, paths)
def addPath(
self, path)
def addPath(self, path: str) -> 'DNode': if path in self: raise ValueError('path {} on node {} already exists'.format(path, self.name)) paths = itertools.chain(self.values(), [DPath(path)]) return DNode(self.name, paths)
def delInterface(
self, path, interface)
def delInterface(self, path: str, interface: DInterface) -> 'DNode': if path not in self: raise ValueError('path {} on node {} does not exist'.format(path, self.name)) if interface.name not in self[path]: raise ValueError('interface {} at path {} on node {} does not exist'.format(interface.name, path, self.name)) paths = (v for v in self.values() if v.name != path) paths = itertools.chain(paths, [self[path].delInterface(interface)]) return DNode(self.name, paths)
def delPath(
self, path)
def delPath(self, path: str) -> 'DNode': if path not in self: raise ValueError('path {} on node {} does not exist'.format(path, self.name)) if self[path]: raise ValueError('path {} on node {} is not empty'.format(path, self.name)) paths = (v for v in self.values() if v.name != path) return DNode(self.name, paths)
def dump(
self)
Converts the supcon.util.NamedList
into a list of 'simple' datastructures.
def dump(self): return { 'name': self.name, 'paths': [value.dump() for value in self.values()] }
def get(
self, key, default=None)
D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.
def get(self, key, default=None): 'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.' try: return self[key] except KeyError: return default
def hasIntf(
self, path, intf)
def hasIntf(self, path: str, intf: str) -> bool: return path in self and intf in self[path]
def hasPath(
self, path)
def hasPath(self, path: str) -> bool: return path in self
def items(
self)
D.items() -> a set-like object providing a view on D's items
def items(self): "D.items() -> a set-like object providing a view on D's items" return ItemsView(self)
def keys(
self)
D.keys() -> a set-like object providing a view on D's keys
def keys(self): "D.keys() -> a set-like object providing a view on D's keys" return KeysView(self)
def values(
self)
D.values() -> an object providing a view on D's values
def values(self): "D.values() -> an object providing a view on D's values" return ValuesView(self)
class DNodes
A readonly map of DNode
instances
class DNodes(supcon.util.NamedList): """A readonly map of `supcon.intf.DNode` instances""" vtype = DNode def hasNode(self, node: str) -> bool: return node in self def hasPath(self, node: str, path: str) -> bool: return node in self and path in self[node] def hasIntf(self, node: str, path: str, intf: str) -> bool: return node in self and path in self[node] and intf in self[node][path] def addNode(self, node: str) -> 'DNodes': if node in self: raise ValueError('node {} already exists'.format(node)) nodes = itertools.chain(self.values(), [DNode(node)]) return DNodes(nodes) def delNode(self, node: str) -> 'DNodes': if node not in self: raise ValueError('node {} does not exist'.format(node)) if self[node]: raise ValueError('node {} is not empty'.format(node)) nodes = (v for v in self.values() if v.name != node) return DNodes(nodes) def addPath(self, node: str, path: str) -> 'DNodes': if node not in self: raise ValueError('node {} does not exist'.format(node)) nodes = (v for v in self.values() if v.name != node) nodes = itertools.chain(nodes, [self[node].addPath(path)]) return DNodes(nodes) def delPath(self, node: str, path: str) -> 'DNodes': if node not in self: raise ValueError('node {} does not exist'.format(node)) nodes = (v for v in self.values() if v.name != node) nodes = itertools.chain(nodes, [self[node].delPath(path)]) return DNodes(nodes) def addInterface(self, node: str, path: str, interface: DInterface) -> 'DNodes': if node not in self: raise ValueError('node {} does not exist'.format(node)) nodes = (v for v in self.values() if v.name != node) nodes = itertools.chain(nodes, [self[node].addInterface(path, interface)]) return DNodes(nodes) def delInterface(self, node: str, path: str, interface: DInterface) -> 'DNodes': if node not in self: raise ValueError('node {} does not exist'.format(node)) nodes = (v for v in self.values() if v.name != node) nodes = itertools.chain(nodes, [self[node].delInterface(path, interface)]) return DNodes(nodes)
Ancestors (in MRO)
- DNodes
- supcon.util.NamedList
- collections.abc.Mapping
- collections.abc.Collection
- collections.abc.Sized
- collections.abc.Iterable
- collections.abc.Container
- supcon.util.Dumpable
- abc.ABC
- builtins.object
Class variables
var vtype
Class Methods
def load(
cls, data)
Converts the given list of 'simple' datastructures data into an instance
of cls, a subclass of supcon.util.NamedList
.
@classmethod def load(cls, data): """ Converts the given list of 'simple' datastructures **data** into an instance of **cls**, a subclass of `supcon.util.NamedList`. """ return cls(data)
def to(
cls, value)
If the the value is an instance of cls, a subclass of
supcon.util.NamedList
, the value is returned. If value is not an instance
of cls the method tries to convert the value into an instance of
cls.
@classmethod def to(cls, value): """ If the the **value** is an instance of **cls**, a subclass of `supcon.util.NamedList`, the value is returned. If value is not an instance of **cls** the method tries to convert the **value** into an instance of **cls**. """ return value if isinstance(value, cls) else cls.load(value)
Methods
def __init__(
self, values=None)
Initializes the supcon.util.NamedList
with the given list of values.
An element of values must be of type supcon.util.NamedList.vtype
or a
'simple' datastructure that can be converted to an instance of
supcon.util.NamedList.vtype
by supcon.util.NamedList.vtype
.load().
def __init__(self, values=None): """ Initializes the `supcon.util.NamedList` with the given list of **values**. An element of **values** must be of type `supcon.util.NamedList.vtype` or a 'simple' datastructure that can be converted to an instance of `supcon.util.NamedList.vtype` by `supcon.util.NamedList.vtype`.load(). """ if values is None: values = [] if not issubclass(self.vtype, Named): raise ValueError('the value type must be a subclass of Named') if not issubclass(self.vtype, Dumpable): raise ValueError('the value type must be a subclass of Dumpable') self.__values = collections.OrderedDict() for value in values: if not isinstance(value, self.vtype): value = self.vtype.load(value) if value.name in self.__values: raise ValueError('value.name must be unique in the given list of values') self.__values[value.name] = value
def addInterface(
self, node, path, interface)
def addInterface(self, node: str, path: str, interface: DInterface) -> 'DNodes': if node not in self: raise ValueError('node {} does not exist'.format(node)) nodes = (v for v in self.values() if v.name != node) nodes = itertools.chain(nodes, [self[node].addInterface(path, interface)]) return DNodes(nodes)
def addNode(
self, node)
def addNode(self, node: str) -> 'DNodes': if node in self: raise ValueError('node {} already exists'.format(node)) nodes = itertools.chain(self.values(), [DNode(node)]) return DNodes(nodes)
def addPath(
self, node, path)
def addPath(self, node: str, path: str) -> 'DNodes': if node not in self: raise ValueError('node {} does not exist'.format(node)) nodes = (v for v in self.values() if v.name != node) nodes = itertools.chain(nodes, [self[node].addPath(path)]) return DNodes(nodes)
def delInterface(
self, node, path, interface)
def delInterface(self, node: str, path: str, interface: DInterface) -> 'DNodes': if node not in self: raise ValueError('node {} does not exist'.format(node)) nodes = (v for v in self.values() if v.name != node) nodes = itertools.chain(nodes, [self[node].delInterface(path, interface)]) return DNodes(nodes)
def delNode(
self, node)
def delNode(self, node: str) -> 'DNodes': if node not in self: raise ValueError('node {} does not exist'.format(node)) if self[node]: raise ValueError('node {} is not empty'.format(node)) nodes = (v for v in self.values() if v.name != node) return DNodes(nodes)
def delPath(
self, node, path)
def delPath(self, node: str, path: str) -> 'DNodes': if node not in self: raise ValueError('node {} does not exist'.format(node)) nodes = (v for v in self.values() if v.name != node) nodes = itertools.chain(nodes, [self[node].delPath(path)]) return DNodes(nodes)
def dump(
self)
Converts the supcon.util.NamedList
into a list of 'simple' datastructures.
def dump(self): """ Converts the `supcon.util.NamedList` into a list of 'simple' datastructures. """ return [value.dump() for value in self.values()]
def get(
self, key, default=None)
D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.
def get(self, key, default=None): 'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.' try: return self[key] except KeyError: return default
def hasIntf(
self, node, path, intf)
def hasIntf(self, node: str, path: str, intf: str) -> bool: return node in self and path in self[node] and intf in self[node][path]
def hasNode(
self, node)
def hasNode(self, node: str) -> bool: return node in self
def hasPath(
self, node, path)
def hasPath(self, node: str, path: str) -> bool: return node in self and path in self[node]
def items(
self)
D.items() -> a set-like object providing a view on D's items
def items(self): "D.items() -> a set-like object providing a view on D's items" return ItemsView(self)
def keys(
self)
D.keys() -> a set-like object providing a view on D's keys
def keys(self): "D.keys() -> a set-like object providing a view on D's keys" return KeysView(self)
def values(
self)
D.values() -> an object providing a view on D's values
def values(self): "D.values() -> an object providing a view on D's values" return ValuesView(self)
class DPath
A named readonly map of DInterface
instances
class DPath(Named, supcon.util.NamedList): """A named readonly map of `supcon.intf.DInterface` instances""" vtype = DInterface regex = re.compile('/(([a-zA-Z0-9_]+/)*[a-zA-Z0-9_]+)?') def __init__(self, name, interfaces=None): """Initializes the Path instance Args: name (str): the name of the argument interfaces (): ... """ if interfaces is None: interfaces = [] Named.__init__(self, name) supcon.util.NamedList.__init__(self, interfaces) def dump(self): return { 'name': self.name, 'interfaces': [value.dump() for value in self.values()] } @classmethod def load(cls, data) -> 'DPath': return cls(**data) def addInterface(self, interface: DInterface) -> 'DPath': if interface.name in self: raise ValueError('interface {} at path {} already exists'.format(interface.name, self.name)) interfaces = itertools.chain(self.values(), [interface]) return DPath(self.name, interfaces) def delInterface(self, interface: DInterface) -> 'DPath': if interface.name not in self: raise ValueError('interface {} at path {} does not exist'.format(interface.name, self.name)) interfaces = (v for v in self.values() if v.name != interface.name) return DPath(self.name, interfaces)
Ancestors (in MRO)
- DPath
- Named
- supcon.util.Named
- supcon.util.NamedList
- collections.abc.Mapping
- collections.abc.Collection
- collections.abc.Sized
- collections.abc.Iterable
- collections.abc.Container
- supcon.util.Dumpable
- abc.ABC
- builtins.object
Class variables
var regex
var vtype
Class Methods
def load(
cls, data)
@classmethod def load(cls, data) -> 'DPath': return cls(**data)
def to(
cls, value)
If the the value is an instance of cls, a subclass of
supcon.util.NamedList
, the value is returned. If value is not an instance
of cls the method tries to convert the value into an instance of
cls.
@classmethod def to(cls, value): """ If the the **value** is an instance of **cls**, a subclass of `supcon.util.NamedList`, the value is returned. If value is not an instance of **cls** the method tries to convert the **value** into an instance of **cls**. """ return value if isinstance(value, cls) else cls.load(value)
def toName(
cls, value)
Converts the value into a name. If this is impossible a ValueError is raised.
Args: value (any): the value Raises: ValueError
@classmethod def toName(cls, value) -> str: """Converts the value into a name. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ value = str(value) if not cls.regex.fullmatch(value): raise ValueError("value {} must match {} fully".format(value, cls.regex.pattern)) return value
Instance variables
Methods
def __init__(
self, name, interfaces=None)
Initializes the Path instance
Args: name (str): the name of the argument interfaces (): ...
def __init__(self, name, interfaces=None): """Initializes the Path instance Args: name (str): the name of the argument interfaces (): ... """ if interfaces is None: interfaces = [] Named.__init__(self, name) supcon.util.NamedList.__init__(self, interfaces)
def addInterface(
self, interface)
def addInterface(self, interface: DInterface) -> 'DPath': if interface.name in self: raise ValueError('interface {} at path {} already exists'.format(interface.name, self.name)) interfaces = itertools.chain(self.values(), [interface]) return DPath(self.name, interfaces)
def delInterface(
self, interface)
def delInterface(self, interface: DInterface) -> 'DPath': if interface.name not in self: raise ValueError('interface {} at path {} does not exist'.format(interface.name, self.name)) interfaces = (v for v in self.values() if v.name != interface.name) return DPath(self.name, interfaces)
def dump(
self)
Converts the supcon.util.NamedList
into a list of 'simple' datastructures.
def dump(self): return { 'name': self.name, 'interfaces': [value.dump() for value in self.values()] }
def get(
self, key, default=None)
D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.
def get(self, key, default=None): 'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.' try: return self[key] except KeyError: return default
def items(
self)
D.items() -> a set-like object providing a view on D's items
def items(self): "D.items() -> a set-like object providing a view on D's items" return ItemsView(self)
def keys(
self)
D.keys() -> a set-like object providing a view on D's keys
def keys(self): "D.keys() -> a set-like object providing a view on D's keys" return KeysView(self)
def values(
self)
D.values() -> an object providing a view on D's values
def values(self): "D.values() -> an object providing a view on D's values" return ValuesView(self)
class Implementation
The base class for interface implementations
class Implementation(object): """The base class for interface implementations""" def __init__(self, interface: DInterface): """ Args: interface (DInterface): the interface that is implemented by this Implementation """ if not isinstance(interface, DInterface): raise ValueError('interface must be an instance of {}'.format(DInterface)) self.__interface = interface self.__callCbs = {} self.__fireCbs = [] @property def intf(self) -> str: """str: The name of the implemented interface""" return self.__interface.name @property def interface(self) -> DInterface: """Interface: The implemented interface""" return self.__interface def setCallCb(self, method: str, cb): """Sets a callback for the given method. The method must be a method of the interface this Implementation implements. The callback must implement the given method. The callback gets called by calls to Implementation.call() Args: method (str): the interface method that the callback implements cb (callable): the callback """ method = DMethod.toName(method) if method in self.__callCbs: raise ValueError('Callback for method {} is already set!'.format(method)) if method not in self.__interface.methods: raise ValueError('Interface has no method {}!'.format(method)) self.__callCbs[method] = cb def call(self, method: str, inArgs) -> defer.Deferred: """Calls the given interface method with the given arguments. This method calls the callback set by Implementation.setCallCb() Args: method (str): the called interface method inArgs (Mapping): a map of input arguments Returns: defer.Deferred: Resolves with the result of the called method """ def validateReturn(outArgs): self.__interface.validateReturn(method, outArgs) return outArgs try: self.__interface.validateCall(method, inArgs) if method not in self.__callCbs: raise ValueError('Callback for method {} is not set!'.format(method)) d = self.__callCbs[method](**inArgs) if not isinstance(d, defer.Deferred): d = defer.succeed(d) d.addCallback(validateReturn) except BaseException as e: traceback.print_exc() d = defer.fail(e) return d def addFireCb(self, cb): """Adds a callback that gets called, when this Implementation fires an event. Args: cb (callable): the callback """ self.__fireCbs.append(cb) def delFireCb(self, cb): """Removes a callback that gets called, when this Implementation fires an event. Args: cb (callable): the callback """ self.__fireCbs.remove(cb) def fire(self, event: str, args): """Fires the given event with the given arguments. Args: event (str): the event name args (collecion.Mapping): the event arguments """ self.__interface.validateEvent(event, args) for cb in self.__fireCbs: cb(event, args)
Ancestors (in MRO)
- Implementation
- builtins.object
Instance variables
var interface
Interface: The implemented interface
var intf
str: The name of the implemented interface
Methods
def __init__(
self, interface)
Args: interface (DInterface): the interface that is implemented by this Implementation
def __init__(self, interface: DInterface): """ Args: interface (DInterface): the interface that is implemented by this Implementation """ if not isinstance(interface, DInterface): raise ValueError('interface must be an instance of {}'.format(DInterface)) self.__interface = interface self.__callCbs = {} self.__fireCbs = []
def addFireCb(
self, cb)
Adds a callback that gets called, when this Implementation fires an event.
Args: cb (callable): the callback
def addFireCb(self, cb): """Adds a callback that gets called, when this Implementation fires an event. Args: cb (callable): the callback """ self.__fireCbs.append(cb)
def call(
self, method, inArgs)
Calls the given interface method with the given arguments. This method calls the callback set by Implementation.setCallCb()
Args: method (str): the called interface method inArgs (Mapping): a map of input arguments Returns: defer.Deferred: Resolves with the result of the called method
def call(self, method: str, inArgs) -> defer.Deferred: """Calls the given interface method with the given arguments. This method calls the callback set by Implementation.setCallCb() Args: method (str): the called interface method inArgs (Mapping): a map of input arguments Returns: defer.Deferred: Resolves with the result of the called method """ def validateReturn(outArgs): self.__interface.validateReturn(method, outArgs) return outArgs try: self.__interface.validateCall(method, inArgs) if method not in self.__callCbs: raise ValueError('Callback for method {} is not set!'.format(method)) d = self.__callCbs[method](**inArgs) if not isinstance(d, defer.Deferred): d = defer.succeed(d) d.addCallback(validateReturn) except BaseException as e: traceback.print_exc() d = defer.fail(e) return d
def delFireCb(
self, cb)
Removes a callback that gets called, when this Implementation fires an event.
Args: cb (callable): the callback
def delFireCb(self, cb): """Removes a callback that gets called, when this Implementation fires an event. Args: cb (callable): the callback """ self.__fireCbs.remove(cb)
def fire(
self, event, args)
Fires the given event with the given arguments.
Args: event (str): the event name args (collecion.Mapping): the event arguments
def fire(self, event: str, args): """Fires the given event with the given arguments. Args: event (str): the event name args (collecion.Mapping): the event arguments """ self.__interface.validateEvent(event, args) for cb in self.__fireCbs: cb(event, args)
def setCallCb(
self, method, cb)
Sets a callback for the given method. The method must be a method of the interface this Implementation implements. The callback must implement the given method. The callback gets called by calls to Implementation.call()
Args: method (str): the interface method that the callback implements cb (callable): the callback
def setCallCb(self, method: str, cb): """Sets a callback for the given method. The method must be a method of the interface this Implementation implements. The callback must implement the given method. The callback gets called by calls to Implementation.call() Args: method (str): the interface method that the callback implements cb (callable): the callback """ method = DMethod.toName(method) if method in self.__callCbs: raise ValueError('Callback for method {} is already set!'.format(method)) if method not in self.__interface.methods: raise ValueError('Interface has no method {}!'.format(method)) self.__callCbs[method] = cb
class Named
A base class for objects with a name.
class Named(supcon.util.Named): """A base class for objects with a name. """ regex = None """re.RegexObject: a regular expression, the name must conform to""" def __init__(self, name): """Initializes the NamedAndDescribed instance Args: name (str): the name of the argument """ self.__name = self.toName(name) @property def name(self) -> str: """str: the name""" return self.__name @classmethod def toName(cls, value) -> str: """Converts the value into a name. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ value = str(value) if not cls.regex.fullmatch(value): raise ValueError("value {} must match {} fully".format(value, cls.regex.pattern)) return value
Ancestors (in MRO)
- Named
- supcon.util.Named
- abc.ABC
- builtins.object
Class variables
var regex
re.RegexObject: a regular expression, the name must conform to
Class Methods
def toName(
cls, value)
Converts the value into a name. If this is impossible a ValueError is raised.
Args: value (any): the value Raises: ValueError
@classmethod def toName(cls, value) -> str: """Converts the value into a name. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ value = str(value) if not cls.regex.fullmatch(value): raise ValueError("value {} must match {} fully".format(value, cls.regex.pattern)) return value
Instance variables
var name
str: the name
Methods
def __init__(
self, name)
Initializes the NamedAndDescribed instance
Args: name (str): the name of the argument
def __init__(self, name): """Initializes the NamedAndDescribed instance Args: name (str): the name of the argument """ self.__name = self.toName(name)
class NamedAndDescribed
A base class for the interface describing classes supcon.intf.Argument
,
supcon.intf.Event
, supcon.intf.Method
and supcon.intf.Interface
that
all have the properties name and description.
class NamedAndDescribed(Named): """A base class for the interface describing classes `supcon.intf.Argument`, `supcon.intf.Event`, `supcon.intf.Method` and `supcon.intf.Interface` that all have the properties name and description.""" def __init__(self, name, description=''): """Initializes the NamedAndDescribed instance Args: name (str): the name of the argument description (str): a description of the argument """ Named.__init__(self, name) self.__description = self.toDescription(description) @property def description(self) -> str: """str: a description""" return self.__description @classmethod def toDescription(cls, value) -> str: """Converts the value into a description. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ return str(value)
Ancestors (in MRO)
- NamedAndDescribed
- Named
- supcon.util.Named
- abc.ABC
- builtins.object
Class variables
var regex
Class Methods
def toDescription(
cls, value)
Converts the value into a description. If this is impossible a ValueError is raised.
Args: value (any): the value Raises: ValueError
@classmethod def toDescription(cls, value) -> str: """Converts the value into a description. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ return str(value)
def toName(
cls, value)
Converts the value into a name. If this is impossible a ValueError is raised.
Args: value (any): the value Raises: ValueError
@classmethod def toName(cls, value) -> str: """Converts the value into a name. If this is impossible a ValueError is raised. Args: value (any): the value Raises: ValueError """ value = str(value) if not cls.regex.fullmatch(value): raise ValueError("value {} must match {} fully".format(value, cls.regex.pattern)) return value
Instance variables
var description
str: a description
var name
str: the name
Methods
def __init__(
self, name, description='')
Initializes the NamedAndDescribed instance
Args: name (str): the name of the argument description (str): a description of the argument
def __init__(self, name, description=''): """Initializes the NamedAndDescribed instance Args: name (str): the name of the argument description (str): a description of the argument """ Named.__init__(self, name) self.__description = self.toDescription(description)
class Node
The Node Interface. This class defines the methods that participants can use to access the supcon bus.
class Node(abc.ABC): """The Node Interface. This class defines the methods that participants can use to access the supcon bus.""" def __init__(self, name): super().__init__() self.__name = self.toName(name) @property def name(self) -> str: """str: The name of the node on the bus""" return self.__name @classmethod def toName(cls, value) -> str: return DNode.toName(value) @abc.abstractmethod def nodes(self) -> DNodes: """list[str]: The currently connected nodes""" raise NotImplementedError() @abc.abstractmethod def connect(self, endpoint): """Connects the node to the given endpoint. If the connection failes or closes the connection gets reestablished with an exponential timeout up to two minutes. Args: endpoint (twisted.internet.interfaces.IStreamClientEndpoint): """ raise NotImplementedError() @abc.abstractmethod def listen(self, endpoint): """Listens at the given endpoint for incoming connections Args: endpoint (twisted.internet.interfaces.IStreamServerEndpoint): """ raise NotImplementedError() @abc.abstractmethod def register(self, path: str, impl: Implementation): """Registers an implementation with the node Args: impl (Implementation): """ raise NotImplementedError() @abc.abstractmethod def unregister(self, path: str, impl: Implementation): """Removes an implementation from the node Args: impl (supcon.intf.Implementation): """ raise NotImplementedError() @abc.abstractmethod def call(self, node: str, path: str, intf: str, method: str, args: dict) -> defer.Deferred: """Calls a method on the bus Args: node (str): a node on the bus path (str): a path on the given node intf (str): an interface at the given path method (str): a method of the given interface args (dict): a dict of method arguments Returns: defer.Deferred: """ raise NotImplementedError() @abc.abstractmethod def on(self, node: str, path: str, intf: str, event: str, cb): """Registers a callback for an event on the bus Args: node (str): a node on the bus path (str): a path on the given node intf (str): an interface at the given path event (str): a method of the given interface cb (callable): a callable that gets called with a dict of event arguments """ raise NotImplementedError() @abc.abstractmethod def off(self, node: str, path: str, intf: str, event: str, cb): """Unregisters a callback for an event on the bus Args: node (str): a node on the bus path (str): a path on the given node intf (str): an interface at the given path event (str): a method of the given interface cb (callable): a callable that gets called with a dict of event arguments """ raise NotImplementedError()
Ancestors (in MRO)
- Node
- abc.ABC
- builtins.object
Class Methods
def toName(
cls, value)
@classmethod def toName(cls, value) -> str: return DNode.toName(value)
Instance variables
var name
str: The name of the node on the bus
Methods
def __init__(
self, name)
Initialize self. See help(type(self)) for accurate signature.
def __init__(self, name): super().__init__() self.__name = self.toName(name)
def call(
self, node, path, intf, method, args)
Calls a method on the bus
Args: node (str): a node on the bus path (str): a path on the given node intf (str): an interface at the given path method (str): a method of the given interface args (dict): a dict of method arguments
Returns: defer.Deferred:
@abc.abstractmethod def call(self, node: str, path: str, intf: str, method: str, args: dict) -> defer.Deferred: """Calls a method on the bus Args: node (str): a node on the bus path (str): a path on the given node intf (str): an interface at the given path method (str): a method of the given interface args (dict): a dict of method arguments Returns: defer.Deferred: """ raise NotImplementedError()
def connect(
self, endpoint)
Connects the node to the given endpoint.
If the connection failes or closes the connection gets reestablished with an exponential timeout up to two minutes.
Args: endpoint (twisted.internet.interfaces.IStreamClientEndpoint):
@abc.abstractmethod def connect(self, endpoint): """Connects the node to the given endpoint. If the connection failes or closes the connection gets reestablished with an exponential timeout up to two minutes. Args: endpoint (twisted.internet.interfaces.IStreamClientEndpoint): """ raise NotImplementedError()
def listen(
self, endpoint)
Listens at the given endpoint for incoming connections
Args: endpoint (twisted.internet.interfaces.IStreamServerEndpoint):
@abc.abstractmethod def listen(self, endpoint): """Listens at the given endpoint for incoming connections Args: endpoint (twisted.internet.interfaces.IStreamServerEndpoint): """ raise NotImplementedError()
def nodes(
self)
list[str]: The currently connected nodes
@abc.abstractmethod def nodes(self) -> DNodes: """list[str]: The currently connected nodes""" raise NotImplementedError()
def off(
self, node, path, intf, event, cb)
Unregisters a callback for an event on the bus
Args: node (str): a node on the bus path (str): a path on the given node intf (str): an interface at the given path event (str): a method of the given interface cb (callable): a callable that gets called with a dict of event arguments
@abc.abstractmethod def off(self, node: str, path: str, intf: str, event: str, cb): """Unregisters a callback for an event on the bus Args: node (str): a node on the bus path (str): a path on the given node intf (str): an interface at the given path event (str): a method of the given interface cb (callable): a callable that gets called with a dict of event arguments """ raise NotImplementedError()
def on(
self, node, path, intf, event, cb)
Registers a callback for an event on the bus
Args: node (str): a node on the bus path (str): a path on the given node intf (str): an interface at the given path event (str): a method of the given interface cb (callable): a callable that gets called with a dict of event arguments
@abc.abstractmethod def on(self, node: str, path: str, intf: str, event: str, cb): """Registers a callback for an event on the bus Args: node (str): a node on the bus path (str): a path on the given node intf (str): an interface at the given path event (str): a method of the given interface cb (callable): a callable that gets called with a dict of event arguments """ raise NotImplementedError()
def register(
self, path, impl)
Registers an implementation with the node
Args: impl (Implementation):
@abc.abstractmethod def register(self, path: str, impl: Implementation): """Registers an implementation with the node Args: impl (Implementation): """ raise NotImplementedError()
def unregister(
self, path, impl)
Removes an implementation from the node
Args: impl (supcon.intf.Implementation):
@abc.abstractmethod def unregister(self, path: str, impl: Implementation): """Removes an implementation from the node Args: impl (supcon.intf.Implementation): """ raise NotImplementedError()
class Object
class Object(object): def __init__(self, interfaces=None): """ Args: interfaces (DInterfaces): the interfaces that are implemented by this Object """ if interfaces is None: interfaces = [] self.__intfs = {} self.__impls = {} def getCallCb(intf): return lambda method, inArgs: self.__call(intf, method, inArgs) for interface in interfaces: if not isinstance(interface, DInterface): raise ValueError('interface must be an instance of {}'.format(DInterface)) self.__intfs[interface.name] = interface implementation = Implementation(interface) callCb = getCallCb(implementation.intf) for method in interface.methods: implementation.setCallCb(method, callCb) self.__impls[implementation.intf] = implementation @property def interfaces(self): return self.__intfs.values() @property def implementations(self): return self.__impls.values() def interface(self, intf): return self.__intfs[intf] def implementation(self, intf): return self.__impls[intf] def __call(self, intf: str, method: str, inArgs) -> defer.Deferred: pass
Ancestors (in MRO)
- Object
- builtins.object
Instance variables
var implementations
var interfaces
Methods
def __init__(
self, interfaces=None)
Args: interfaces (DInterfaces): the interfaces that are implemented by this Object
def __init__(self, interfaces=None): """ Args: interfaces (DInterfaces): the interfaces that are implemented by this Object """ if interfaces is None: interfaces = [] self.__intfs = {} self.__impls = {} def getCallCb(intf): return lambda method, inArgs: self.__call(intf, method, inArgs) for interface in interfaces: if not isinstance(interface, DInterface): raise ValueError('interface must be an instance of {}'.format(DInterface)) self.__intfs[interface.name] = interface implementation = Implementation(interface) callCb = getCallCb(implementation.intf) for method in interface.methods: implementation.setCallCb(method, callCb) self.__impls[implementation.intf] = implementation
def implementation(
self, intf)
def implementation(self, intf): return self.__impls[intf]
def interface(
self, intf)
def interface(self, intf): return self.__intfs[intf]