mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2024-12-29 06:32:40 -06:00
100 lines
3 KiB
Python
Executable file
100 lines
3 KiB
Python
Executable file
"""
|
|
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)
|
|
|
|
|