]> git.ipfire.org Git - thirdparty/python-fints.git/commitdiff
Add some developer documentation
authorHenryk Plötz <henryk@ploetzli.ch>
Fri, 10 Aug 2018 02:31:16 +0000 (04:31 +0200)
committerRaphael Michel <mail@raphaelmichel.de>
Mon, 3 Dec 2018 18:34:17 +0000 (19:34 +0100)
docs/developer.rst [new file with mode: 0644]
docs/index.rst
fints/formals.py
fints/segments/__init__.py

diff --git a/docs/developer.rst b/docs/developer.rst
new file mode 100644 (file)
index 0000000..7205d25
--- /dev/null
@@ -0,0 +1,54 @@
+Developer documentation/API
+===========================
+
+FinTS Segments
+--------------
+A segment is the core communication workhorse in FinTS. Each segment has a header of fixed format, which includes the segment type ("Segmentkennung"), number within the message, version, and, optionally, the number of the segment of another message it is in response or relation to ("Bezugssegment").
+
+The header is followed by a nested structure of fields and groups of fields, the exact specification of which depends on the segment type and version.
+
+In ``python-fints`` all segment classes derive from  ``FinTS3Segment``, which specifies the ``header`` attribute of ``SegmentHeader`` type.
+
+.. autoclass:: fints.segments.FinTS3Segment
+   :members:
+   :inherited-members: print_nested
+
+   .. attribute:: TYPE
+
+      Segment type. Will be determined from the class name in subclasses, if the class name consists only of uppercase characters followed by decimal digits. Subclasses may explicitly set a class attribute instead.
+
+   .. attribute:: VERSION
+
+      Segment version. Will be determined from the class name in subclasses, if the class name consists only of uppercase characters followed by decimal digits. Subclasses may explicitly set a class attribute instead.
+
+   .. classmethod:: find_subclass(segment: list)
+
+      Parse the given ``segment`` parameter as a ``SegmentHeader`` and return a subclass with matching type and version class attributes.
+
+.. autoclass:: fints.formals.SegmentHeader
+   :members:
+
+The ``FinTS3Segment`` class and its base classes employ a number of dynamic programming techniques so that derived classes need only specify the name, order and type of fields and all type conversion, construction etc. will take place automatically. All derived classes basically should behave "as expected", returning only native Python datatypes.
+
+Consider this example segment class:
+
+.. code-block:: python
+
+    class HNHBS1(FinTS3Segment):
+        message_number = DataElementField(type='num', max_length=4)
+
+Calling ``print_nested`` on an instance of this class might yield:
+
+.. code-block:: python
+
+    fints.segments.HNHBS1(
+        header = fints.formals.SegmentHeader('HNHBS', 4, 1),
+        message_number = 1,
+    )
+
+All Segments
+____________
+
+.. automodule:: fints.segments
+    :members:
+    :inherited-members:
index 28abf6c5de80138f57cef58f077e1732472db349..165e5dcc085fb6fb020b6914e0eff39d088503dc 100644 (file)
@@ -19,3 +19,4 @@ Documentation content
    transfers
    debits
    tested
+   developer
index 8739eca0f563df7447c2412c9f3e33e8cb0ab9a2..eca4516ac8954cf810d14de5b0dea5b956022f3f 100644 (file)
@@ -89,7 +89,7 @@ class ValueList:
         stream.write( (prefix + level*indent) + "]{}\n".format(trailer) )
 
 class Field:
-    def __init__(self, length=None, min_length=None, max_length=None, count=None, min_count=None, max_count=None, required=True):
+    def __init__(self, length=None, min_length=None, max_length=None, count=None, min_count=None, max_count=None, required=True, _d=None):
         if length is not None and (min_length is not None or max_length is not None):
             raise ValueError("May not specify both 'length' AND 'min_length'/'max_length'")
         if count is not None and (min_count is not None or max_count is not None):
@@ -106,6 +106,8 @@ class Field:
         if not self.count and not self.min_count and not self.max_count:
             self.count = 1
 
+        self.__doc__ = _d
+
     def _default_value(self):
         return None
 
@@ -463,6 +465,9 @@ class Container(metaclass=ContainerMeta):
         )
 
     def print_nested(self, stream=None, level=0, indent="    ", prefix="", first_level_indent=True, trailer=""):
+        """Structured nested print of the object to the given stream.
+
+        The print-out is eval()able to reconstruct the object."""
         import sys
         stream = stream or sys.stdout
 
@@ -504,10 +509,11 @@ class DataElementGroup(Container):
     pass
 
 class SegmentHeader(ShortReprMixin, DataElementGroup):
-    type = AlphanumericField(max_length=6)
-    number = NumericField(max_length=3)
-    version = NumericField(max_length=3)
-    reference = NumericField(max_length=3, required=False)
+    "Segmentkopf"
+    type = AlphanumericField(max_length=6, _d='Segmentkennung')
+    number = NumericField(max_length=3, _d='Segmentnummer')
+    version = NumericField(max_length=3, _d='Segmentversion')
+    reference = NumericField(max_length=3, required=False, _d='Bezugssegment')
 
 class ReferenceMessage(DataElementGroup):
     dialogue_id = DataElementField(type='id')
index 917706ff019c4cb97e79531a7d8964172f3f93d2..4097818280dc05b12059263af7815415c2122c4e 100644 (file)
@@ -34,7 +34,7 @@ class FinTS3SegmentMeta(ContainerMeta):
         return retval
 
 class FinTS3Segment(Container, SubclassesMixin, metaclass=FinTS3SegmentMeta):
-    header = DataElementGroupField(type=SegmentHeader)
+    header = DataElementGroupField(type=SegmentHeader, _d="Segmentkopf")
 
     @classproperty
     def TYPE(cls):
@@ -147,9 +147,9 @@ class HISYN4(FinTS3Segment):
     security_reference_digital_signature = DataElementField(type='num', max_length=16, required=False)
 
 class ParameterSegment(FinTS3Segment):
-    max_number_tasks = DataElementField(type='num', max_length=3)
-    min_number_signatures = DataElementField(type='num', length=1)
-    security_class = DataElementField(type='num', length=1)
+    max_number_tasks = DataElementField(type='num', max_length=3, _d="Maximale Anzahl Aufträge")
+    min_number_signatures = DataElementField(type='num', length=1, _d="Anzahl Signaturen mindestens")
+    security_class = DataElementField(type='num', length=1, _d="Sicherheitsklasse")
 
 class HITANS1(ParameterSegment):
     parameters = DataElementGroupField(type=ParameterTwostepTAN1)
@@ -158,5 +158,10 @@ class HITANS3(ParameterSegment):
     parameters = DataElementGroupField(type=ParameterTwostepTAN3)
 
 class HIPINS1(ParameterSegment):
-    parameters = DataElementGroupField(type=ParameterPinTan)
+    """PIN/TAN-spezifische Informationen, version 1
+
+    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN 
+    """
+    parameters = DataElementGroupField(type=ParameterPinTan, _d="Parameter PIN/TAN-spezifische Informationen") 
+