Graph-IT

supcon.util module

# -*- coding: utf-8 -*-

import abc

import asyncio
import collections
import collections.abc

import twisted.internet.defer

def schedule(obj):
  if asyncio.iscoroutine(obj):
    obj = twisted.internet.defer.ensureDeferred(obj)
  return obj

class Dumpable(abc.ABC):
  """
  The abstract base class `supcon.util.Dumpable`.

  Implementations of this abstract base class can be converted to and from
  'simple' datastructures containing only ints, floats, strings, lists and
  dicts. These simple datastructures can be send and received by the supcon
  bus. If you only ever use simple datastructures you can ignore this class.
  """

  @abc.abstractmethod
  def dump(self):
    """
    Converts the `supcon.util.Dumpable` into a 'simple' datastructure.
    """
    pass

  @abc.abstractclassmethod
  def load(cls, data):
    """
    Converts the given 'simple' datastructure **data** into an instance of
    **cls**, a subclass of `supcon.util.Dumpable`
    """
    pass

class Named(abc.ABC):
  """
  The abstract base class `supcon.util.Named`.

  Implementations of this abstract base class must have a property
  `supcon.util.Named.name`, that can be used as a key in a dictionary.
  """

  @property
  @abc.abstractmethod
  def name(self) -> str:
    """
    The name of the instance. Is useable as a dictionary key.
    """
    pass

class NamedList(collections.abc.Mapping, Dumpable):
  """
  A `supcon.util.NamedList` is an ordered, readonly dictionary of
  `supcon.util.Named` and `supcon.util.Dumpable` elements of value type
  `supcon.util.NamedList.vtype`.

  The class `supcon.util.NamedList` itself can not be instantiated. It must be
  subclassed and the class property `supcon.util.NamedList.vtype` set. The class
  property `supcon.util.NamedList.vtype` denotes the type of the elements that
  the list can contain. The type `supcon.util.NamedList.vtype` must be a
  subclass of `supcon.util.Named` and of `supcon.util.Dumpable`. Elements in the
  `supcon.util.NamedList.vtype` can be accessed by the values of their
  `supcon.util.Named.name` property.
  """

  vtype = None
  """
  Must be assigned in a subclass of `supcon.util.NamedList` to a subclass
  of `supcon.util.Named` and `supcon.util.Dumpable`
  """

  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 __getitem__(self, key):
    return self.__values[key]

  def __iter__(self):
    return iter(self.__values)

  def __len__(self):
    return len(self.__values)

  def __repr__(self):
    return "{}.{}({})".format(
      self.__module__, self.__class__.__name__,
      ', '.join([repr(v) for k, v in self.items()])
    )

  def dump(self):
    """
    Converts the `supcon.util.NamedList` into a list of 'simple' datastructures.
    """
    return [value.dump() for value in self.values()]

  @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)

  @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)

class EventEmitter(object):

  def __init__(self):
    self.__callbacks = {}

  def on(self, event, callback):
    """
    Registers the given callback for the given event
    """
    if type not in self.__callbacks:
      self.__callbacks[event] = {}
    self.__callbacks[event][id(callback)] = callback
    return lambda: self.off(event, callback)

  def off(self, event, callback):
    """
    Unregisters the given callback for the given event
    """
    if event not in self.__callbacks:
      return
    if id(callback) not in self.__callbacks[event]:
      return
    del self.__callbacks[event][id(callback)]

  def emit(self, event, *args):
    """
    Calls all callbacks for the given event with the given arguments
    """
    if event not in self.__callbacks:
      return
    for callback in self.__callbacks[event].values():
      schedule(callback(*args))

Functions

def schedule(

obj)

def schedule(obj):
  if asyncio.iscoroutine(obj):
    obj = twisted.internet.defer.ensureDeferred(obj)
  return obj

Classes

class Dumpable

The abstract base class Dumpable.

Implementations of this abstract base class can be converted to and from 'simple' datastructures containing only ints, floats, strings, lists and dicts. These simple datastructures can be send and received by the supcon bus. If you only ever use simple datastructures you can ignore this class.

class Dumpable(abc.ABC):
  """
  The abstract base class `supcon.util.Dumpable`.

  Implementations of this abstract base class can be converted to and from
  'simple' datastructures containing only ints, floats, strings, lists and
  dicts. These simple datastructures can be send and received by the supcon
  bus. If you only ever use simple datastructures you can ignore this class.
  """

  @abc.abstractmethod
  def dump(self):
    """
    Converts the `supcon.util.Dumpable` into a 'simple' datastructure.
    """
    pass

  @abc.abstractclassmethod
  def load(cls, data):
    """
    Converts the given 'simple' datastructure **data** into an instance of
    **cls**, a subclass of `supcon.util.Dumpable`
    """
    pass

Ancestors (in MRO)

Class Methods

def load(

cls, data)

Converts the given 'simple' datastructure data into an instance of cls, a subclass of Dumpable

@abc.abstractclassmethod
def load(cls, data):
  """
  Converts the given 'simple' datastructure **data** into an instance of
  **cls**, a subclass of `supcon.util.Dumpable`
  """
  pass

Methods

def dump(

self)

Converts the Dumpable into a 'simple' datastructure.

@abc.abstractmethod
def dump(self):
  """
  Converts the `supcon.util.Dumpable` into a 'simple' datastructure.
  """
  pass

class EventEmitter

class EventEmitter(object):

  def __init__(self):
    self.__callbacks = {}

  def on(self, event, callback):
    """
    Registers the given callback for the given event
    """
    if type not in self.__callbacks:
      self.__callbacks[event] = {}
    self.__callbacks[event][id(callback)] = callback
    return lambda: self.off(event, callback)

  def off(self, event, callback):
    """
    Unregisters the given callback for the given event
    """
    if event not in self.__callbacks:
      return
    if id(callback) not in self.__callbacks[event]:
      return
    del self.__callbacks[event][id(callback)]

  def emit(self, event, *args):
    """
    Calls all callbacks for the given event with the given arguments
    """
    if event not in self.__callbacks:
      return
    for callback in self.__callbacks[event].values():
      schedule(callback(*args))

Ancestors (in MRO)

Methods

def __init__(

self)

Initialize self. See help(type(self)) for accurate signature.

def __init__(self):
  self.__callbacks = {}

def emit(

self, event, *args)

Calls all callbacks for the given event with the given arguments

def emit(self, event, *args):
  """
  Calls all callbacks for the given event with the given arguments
  """
  if event not in self.__callbacks:
    return
  for callback in self.__callbacks[event].values():
    schedule(callback(*args))

def off(

self, event, callback)

Unregisters the given callback for the given event

def off(self, event, callback):
  """
  Unregisters the given callback for the given event
  """
  if event not in self.__callbacks:
    return
  if id(callback) not in self.__callbacks[event]:
    return
  del self.__callbacks[event][id(callback)]

def on(

self, event, callback)

Registers the given callback for the given event

def on(self, event, callback):
  """
  Registers the given callback for the given event
  """
  if type not in self.__callbacks:
    self.__callbacks[event] = {}
  self.__callbacks[event][id(callback)] = callback
  return lambda: self.off(event, callback)

class Named

The abstract base class Named.

Implementations of this abstract base class must have a property name, that can be used as a key in a dictionary.

class Named(abc.ABC):
  """
  The abstract base class `supcon.util.Named`.

  Implementations of this abstract base class must have a property
  `supcon.util.Named.name`, that can be used as a key in a dictionary.
  """

  @property
  @abc.abstractmethod
  def name(self) -> str:
    """
    The name of the instance. Is useable as a dictionary key.
    """
    pass

Ancestors (in MRO)

  • Named
  • abc.ABC
  • builtins.object

Instance variables

var name

The name of the instance. Is useable as a dictionary key.

class NamedList

A NamedList is an ordered, readonly dictionary of Named and Dumpable elements of value type vtype.

The class NamedList itself can not be instantiated. It must be subclassed and the class property vtype set. The class property vtype denotes the type of the elements that the list can contain. The type vtype must be a subclass of Named and of Dumpable. Elements in the vtype can be accessed by the values of their name property.

class NamedList(collections.abc.Mapping, Dumpable):
  """
  A `supcon.util.NamedList` is an ordered, readonly dictionary of
  `supcon.util.Named` and `supcon.util.Dumpable` elements of value type
  `supcon.util.NamedList.vtype`.

  The class `supcon.util.NamedList` itself can not be instantiated. It must be
  subclassed and the class property `supcon.util.NamedList.vtype` set. The class
  property `supcon.util.NamedList.vtype` denotes the type of the elements that
  the list can contain. The type `supcon.util.NamedList.vtype` must be a
  subclass of `supcon.util.Named` and of `supcon.util.Dumpable`. Elements in the
  `supcon.util.NamedList.vtype` can be accessed by the values of their
  `supcon.util.Named.name` property.
  """

  vtype = None
  """
  Must be assigned in a subclass of `supcon.util.NamedList` to a subclass
  of `supcon.util.Named` and `supcon.util.Dumpable`
  """

  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 __getitem__(self, key):
    return self.__values[key]

  def __iter__(self):
    return iter(self.__values)

  def __len__(self):
    return len(self.__values)

  def __repr__(self):
    return "{}.{}({})".format(
      self.__module__, self.__class__.__name__,
      ', '.join([repr(v) for k, v in self.items()])
    )

  def dump(self):
    """
    Converts the `supcon.util.NamedList` into a list of 'simple' datastructures.
    """
    return [value.dump() for value in self.values()]

  @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)

  @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)

Ancestors (in MRO)

  • NamedList
  • collections.abc.Mapping
  • collections.abc.Collection
  • collections.abc.Sized
  • collections.abc.Iterable
  • collections.abc.Container
  • Dumpable
  • abc.ABC
  • builtins.object

Class variables

var vtype

Must be assigned in a subclass of NamedList to a subclass of Named and Dumpable

Class Methods

def load(

cls, data)

Converts the given list of 'simple' datastructures data into an instance of cls, a subclass of 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 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 NamedList with the given list of values.

An element of values must be of type vtype or a 'simple' datastructure that can be converted to an instance of vtype by 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 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)