""" Provides useful functions and classes. Most useful are probably printTreeDocs and printTreeSpec. :copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved. :license: BSD, see LICENSE_BSD_Simple.txt for details. """ import sys from .. import py2and3 __all__ = ('printImported', 'StructMsg', 'Callback', 'Enum' ) def printImported(): """Output a list of pubsub modules imported so far""" ll = [mod for mod in sys.modules.keys() if mod.find('pubsub') >= 0] # iter keys ok ll.sort() py2and3.print_('\n'.join(ll)) class StructMsg: """ This *can* be used to package message data. Each of the keyword args given at construction will be stored as a member of the 'data' member of instance. E.g. "m=Message2(a=1, b='b')" would succeed "assert m.data.a==1" and "assert m.data.b=='b'". However, use of Message2 makes your messaging code less documented and harder to debug. """ def __init__(self, **kwargs): class Data: pass self.data = Data() self.data.__dict__.update(kwargs) class Callback: """This can be used to wrap functions that are referenced by class data if the data should be called as a function. E.g. given >>> def func(): pass >>> class A: ....def __init__(self): self.a = func then doing >>> boo=A(); boo.a() will fail since Python will try to call a() as a method of boo, whereas a() is a free function. But if you have instead "self.a = Callback(func)", then "boo.a()" works as expected. """ def __init__(self, callable_): self.__callable = callable_ def __call__(self, *args, **kwargs): return self.__callable(*args, **kwargs) class Enum: """Used only internally. Represent one value out of an enumeration set. It is meant to be used as:: class YourAllowedValues: enum1 = Enum() # or: enum2 = Enum(value) # or: enum3 = Enum(value, 'descriptionLine1') # or: enum3 = Enum(None, 'descriptionLine1', 'descriptionLine2', ...) val = YourAllowedValues.enum1 ... if val is YourAllowedValues.enum1: ... """ nextValue = 0 values = set() def __init__(self, value=None, *desc): """Use value if given, otherwise use next integer.""" self.desc = '\n'.join(desc) if value is None: assert Enum.nextValue not in Enum.values self.value = Enum.nextValue Enum.values.add(self.value) Enum.nextValue += 1 # check that we haven't run out of integers! if Enum.nextValue == 0: raise RuntimeError('Ran out of enumeration values?') else: try: value + Enum.nextValue raise ValueError('Not allowed to assign integer to enumerations') except TypeError: pass self.value = value if self.value not in Enum.values: Enum.values.add(self.value)