enhance documentation
- flatten hierarchy (some links do not work when using folders) + fix a bug with the redorder flag in Override + allow removal of parameters + clean description using inspect.cleandoc Change-Id: I3dde4f4cb29c46e8a21014f1fad7aa3ad610a1bf
This commit is contained in:
@@ -126,6 +126,10 @@ class DataType(HasProperties):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def short_doc(self):
|
||||
"""short description for automatic extension of doc strings"""
|
||||
return None
|
||||
|
||||
|
||||
class Stub(DataType):
|
||||
"""incomplete datatype, to be replaced with a proper one later during module load
|
||||
@@ -155,6 +159,10 @@ class Stub(DataType):
|
||||
if isinstance(stub, cls):
|
||||
prop.datatype = globals()[stub.name](*stub.args)
|
||||
|
||||
def short_doc(self):
|
||||
return self.name.replace('Type', '').replace('Range', '').lower()
|
||||
|
||||
|
||||
# SECoP types:
|
||||
|
||||
|
||||
@@ -163,6 +171,7 @@ class FloatRange(DataType):
|
||||
|
||||
:param minval: (property **min**)
|
||||
:param maxval: (property **max**)
|
||||
:param properties: any of the properties below
|
||||
"""
|
||||
|
||||
properties = {
|
||||
@@ -240,6 +249,9 @@ class FloatRange(DataType):
|
||||
other(max(sys.float_info.min, self.min))
|
||||
other(min(sys.float_info.max, self.max))
|
||||
|
||||
def short_doc(self):
|
||||
return 'float'
|
||||
|
||||
|
||||
class IntRange(DataType):
|
||||
"""restricted int type
|
||||
@@ -304,15 +316,25 @@ class IntRange(DataType):
|
||||
for i in range(self.min, self.max + 1):
|
||||
other(i)
|
||||
|
||||
def short_doc(self):
|
||||
return 'int'
|
||||
|
||||
|
||||
class ScaledInteger(DataType):
|
||||
"""scaled integer (= fixed resolution float) type
|
||||
|
||||
| In general *ScaledInteger* is needed only in special cases,
|
||||
e.g. when the a SEC node is running on very limited hardware
|
||||
without floating point support.
|
||||
| Please use *FloatRange* instead.
|
||||
|
||||
:param minval: (property **min**)
|
||||
:param maxval: (property **max**)
|
||||
:param properties: any of the properties below
|
||||
|
||||
note: limits are for the scaled float value
|
||||
the scale is only used for calculating to/from transport serialisation
|
||||
{properties}
|
||||
:note: - limits are for the scaled float value
|
||||
- the scale is only used for calculating to/from transport serialisation
|
||||
"""
|
||||
properties = {
|
||||
'scale': Property('scale factor', FloatRange(sys.float_info.min), extname='scale', mandatory=True),
|
||||
@@ -413,14 +435,17 @@ class ScaledInteger(DataType):
|
||||
other(self.min)
|
||||
other(self.max)
|
||||
|
||||
def short_doc(self):
|
||||
return 'float'
|
||||
|
||||
|
||||
class EnumType(DataType):
|
||||
"""enumeration
|
||||
|
||||
:param enum_or_name: the name of the Enum or an Enum to inherit from
|
||||
:param members: members=<members dict>
|
||||
:param members: each argument denotes <member name>=<member int value>
|
||||
|
||||
other keywords: (additional) members
|
||||
exception: use members=<member dict> to add members from a dict
|
||||
"""
|
||||
def __init__(self, enum_or_name='', **members):
|
||||
super().__init__()
|
||||
@@ -466,6 +491,9 @@ class EnumType(DataType):
|
||||
for m in self._enum.members:
|
||||
other(m)
|
||||
|
||||
def short_doc(self):
|
||||
return 'one of %s' % str(tuple(self._enum.keys()))
|
||||
|
||||
|
||||
class BLOBType(DataType):
|
||||
"""binary large object
|
||||
@@ -547,11 +575,11 @@ class StringType(DataType):
|
||||
Stub('BoolType'), extname='isUTF8', default=False),
|
||||
}
|
||||
|
||||
def __init__(self, minchars=0, maxchars=None, **properties):
|
||||
def __init__(self, minchars=0, maxchars=None, isUTF8=False):
|
||||
super().__init__()
|
||||
if maxchars is None:
|
||||
maxchars = minchars or UNLIMITED
|
||||
self.set_properties(minchars=minchars, maxchars=maxchars, **properties)
|
||||
self.set_properties(minchars=minchars, maxchars=maxchars, isUTF8=isUTF8)
|
||||
|
||||
def checkProperties(self):
|
||||
self.default = ' ' * self.minchars
|
||||
@@ -607,12 +635,24 @@ class StringType(DataType):
|
||||
except AttributeError:
|
||||
raise BadValueError('incompatible datatypes')
|
||||
|
||||
def short_doc(self):
|
||||
return 'str'
|
||||
|
||||
|
||||
# TextType is a special StringType intended for longer texts (i.e. embedding \n),
|
||||
# whereas StringType is supposed to not contain '\n'
|
||||
# unfortunately, SECoP makes no distinction here....
|
||||
# note: content is supposed to follow the format of a git commit message, i.e. a line of text, 2 '\n' + a longer explanation
|
||||
class TextType(StringType):
|
||||
"""special string type, intended for longer texts
|
||||
|
||||
:param maxchars: maximum number of characters
|
||||
|
||||
whereas StringType is supposed to not contain '\n'
|
||||
unfortunately, SECoP makes no distinction here....
|
||||
note: content is supposed to follow the format of a git commit message,
|
||||
i.e. a line of text, 2 '\n' + a longer explanation
|
||||
"""
|
||||
def __init__(self, maxchars=None):
|
||||
if maxchars is None:
|
||||
maxchars = UNLIMITED
|
||||
@@ -667,6 +707,9 @@ class BoolType(DataType):
|
||||
other(False)
|
||||
other(True)
|
||||
|
||||
def short_doc(self):
|
||||
return 'bool'
|
||||
|
||||
|
||||
Stub.fix_datatypes()
|
||||
|
||||
@@ -678,6 +721,7 @@ Stub.fix_datatypes()
|
||||
class ArrayOf(DataType):
|
||||
"""data structure with fields of homogeneous type
|
||||
|
||||
:param members: the datatype for all elements
|
||||
"""
|
||||
properties = {
|
||||
'minlen': Property('minimum number of elements', IntRange(0), extname='minlen',
|
||||
@@ -774,10 +818,14 @@ class ArrayOf(DataType):
|
||||
except AttributeError:
|
||||
raise BadValueError('incompatible datatypes')
|
||||
|
||||
def short_doc(self):
|
||||
return 'array of %s' % self.members.short_doc()
|
||||
|
||||
|
||||
class TupleOf(DataType):
|
||||
"""data structure with fields of inhomogeneous type
|
||||
|
||||
:param members: each argument is a datatype of an element
|
||||
"""
|
||||
|
||||
def __init__(self, *members):
|
||||
@@ -841,6 +889,9 @@ class TupleOf(DataType):
|
||||
for a, b in zip(self.members, other.members):
|
||||
a.compatible(b)
|
||||
|
||||
def short_doc(self):
|
||||
return 'tuple of (%s)' % ', '.join(m.short_doc() for m in self.members)
|
||||
|
||||
|
||||
class ImmutableDict(dict):
|
||||
def _no(self, *args, **kwds):
|
||||
@@ -851,6 +902,8 @@ class ImmutableDict(dict):
|
||||
class StructOf(DataType):
|
||||
"""data structure with named fields
|
||||
|
||||
:param optional: (*sequence*) optional members
|
||||
:param members: each argument denotes <member name>=<member data type>
|
||||
"""
|
||||
def __init__(self, optional=None, **members):
|
||||
super().__init__()
|
||||
@@ -926,11 +979,18 @@ class StructOf(DataType):
|
||||
except (AttributeError, TypeError, KeyError):
|
||||
raise BadValueError('incompatible datatypes')
|
||||
|
||||
def short_doc(self):
|
||||
return 'dict'
|
||||
|
||||
|
||||
class CommandType(DataType):
|
||||
"""command
|
||||
|
||||
a pseudo datatype for commands with arguments and return values
|
||||
|
||||
:param argument: None or the data type of the argument. multiple arguments may be simulated
|
||||
by TupleOf or StructOf
|
||||
:param result: None or the data type of the result
|
||||
"""
|
||||
IS_COMMAND = True
|
||||
|
||||
@@ -989,10 +1049,16 @@ class CommandType(DataType):
|
||||
except AttributeError:
|
||||
raise BadValueError('incompatible datatypes')
|
||||
|
||||
def short_doc(self):
|
||||
argument = self.argument.short_doc() if self.argument else ''
|
||||
result = ' -> %s' % self.argument.short_doc() if self.result else ''
|
||||
return '(%s)%s' % (argument, result) # return argument list only
|
||||
|
||||
|
||||
# internally used datatypes (i.e. only for programming the SEC-node)
|
||||
|
||||
class DataTypeType(DataType):
|
||||
"""DataType type"""
|
||||
def __call__(self, value):
|
||||
"""check if given value (a python obj) is a valid datatype
|
||||
|
||||
@@ -1036,7 +1102,9 @@ class ValueType(DataType):
|
||||
|
||||
|
||||
class NoneOr(DataType):
|
||||
"""validates a None or smth. else"""
|
||||
"""validates a None or other
|
||||
|
||||
:param other: the other datatype"""
|
||||
default = None
|
||||
|
||||
def __init__(self, other):
|
||||
@@ -1051,8 +1119,16 @@ class NoneOr(DataType):
|
||||
return None
|
||||
return self.other.export_value(value)
|
||||
|
||||
def short_doc(self):
|
||||
other = self.other.short_doc()
|
||||
return '%s or None' % other if other else None
|
||||
|
||||
|
||||
class OrType(DataType):
|
||||
"""validates one of the
|
||||
|
||||
:param types: each argument denotes one allowed type
|
||||
"""
|
||||
def __init__(self, *types):
|
||||
super().__init__()
|
||||
self.types = types
|
||||
@@ -1066,6 +1142,12 @@ class OrType(DataType):
|
||||
pass
|
||||
raise BadValueError("Invalid Value, must conform to one of %s" % (', '.join((str(t) for t in self.types))))
|
||||
|
||||
def short_doc(self):
|
||||
types = [t.short_doc() for t in self.types]
|
||||
if None in types:
|
||||
return None
|
||||
return ' or '.join(types)
|
||||
|
||||
|
||||
Int8 = IntRange(-(1 << 7), (1 << 7) - 1)
|
||||
Int16 = IntRange(-(1 << 15), (1 << 15) - 1)
|
||||
@@ -1079,6 +1161,12 @@ UInt64 = IntRange(0, (1 << 64) - 1)
|
||||
|
||||
# Goodie: Convenience Datatypes for Programming
|
||||
class LimitsType(TupleOf):
|
||||
"""limit (min, max) tuple
|
||||
|
||||
:param members: the type of both members
|
||||
|
||||
checks for min <= max
|
||||
"""
|
||||
def __init__(self, members):
|
||||
TupleOf.__init__(self, members, members)
|
||||
|
||||
@@ -1090,7 +1178,13 @@ class LimitsType(TupleOf):
|
||||
|
||||
|
||||
class StatusType(TupleOf):
|
||||
# shorten initialisation and allow acces to status enumMembers from status values
|
||||
"""SECoP status type
|
||||
|
||||
:param enum: the status code enum type
|
||||
|
||||
allows to access enum members directly
|
||||
"""
|
||||
|
||||
def __init__(self, enum):
|
||||
TupleOf.__init__(self, EnumType(enum), StringType())
|
||||
self.enum = enum
|
||||
|
||||
Reference in New Issue
Block a user