.. note::
- In general parsing followed by serialization is not idempotent: A message may contain empty list elements at the end, but our parser will never generate them.
+ In general parsing followed by serialization is not idempotent: A message may contain empty list elements at the end, but our serializer will never generate them.
FinTS Segment Sequence
----------------------
from contextlib import suppress
import fints.types
-from fints.utils import Password, SubclassesMixin
+from fints.utils import (
+ DocTypeMixin, FieldRenderFormatStringMixin,
+ FixedLengthMixin, Password, SubclassesMixin,
+)
class Field:
self.type = type or getattr(self.__class__, 'type', None)
-class DocTypeMixin:
- _DOC_TYPE = None
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- type_ = self._DOC_TYPE
- if type_ is None:
- if isinstance(getattr(self, 'type', None), type):
- type_ = getattr(self, 'type')
-
- if type_ is not None:
- if not self.__doc__:
- self.__doc__ = ""
-
- name = type_.__name__
- if type_.__module__ != 'builtins':
- name = "{}.{}".format(type_.__module__, name)
-
- self.__doc__ = self.__doc__ + "\n\n:type: :class:`{}`".format(name)
-
class DataElementField(DocTypeMixin, TypedField):
pass
-class FieldRenderFormatStringMixin:
- _FORMAT_STRING = None
-
- def _render_value(self, value):
- retval = self._FORMAT_STRING.format(value)
- self._check_value_length(retval)
-
- return retval
-
class ContainerField(TypedField):
def _check_value(self, value):
if self.type:
def _parse_value(self, value): return bytes(value)
-class FixedLengthMixin:
- _FIXED_LENGTH = [None, None, None]
- _DOC_TYPE = str
-
- def __init__(self, *args, **kwargs):
- for i, a in enumerate(('length', 'min_length', 'max_length')):
- kwargs[a] = self._FIXED_LENGTH[i] if len(self._FIXED_LENGTH) > i else None
-
- super().__init__(*args, **kwargs)
-
class IDField(FixedLengthMixin, AlphanumericField):
type = 'id'
_DOC_TYPE = str
import re
-from fints.types import * # The order is important!
+from fints.types import * # The order is important!
from fints.fields import *
+from fints.utils import ShortReprMixin
-class ShortReprMixin:
- def __repr__(self):
- return "{}{}({})".format(
- "{}.".format(self.__class__.__module__),
- self.__class__.__name__,
- ", ".join(
- ("{!r}".format(value) if not name.startswith("_") else "{}={!r}".format(name, value))
- for (name, value) in self._repr_items
- )
- )
-
- def print_nested(self, stream=None, level=0, indent=" ", prefix="", first_level_indent=True, trailer=""):
- stream.write(
- ( (prefix + level*indent) if first_level_indent else "")
- + "{!r}{}\n".format(self, trailer)
- )
-
class DataElementGroup(Container):
pass
yield cls
+class DocTypeMixin:
+ _DOC_TYPE = None
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ type_ = self._DOC_TYPE
+ if type_ is None:
+ if isinstance(getattr(self, 'type', None), type):
+ type_ = getattr(self, 'type')
+
+ if type_ is not None:
+ if not self.__doc__:
+ self.__doc__ = ""
+
+ name = type_.__name__
+ if type_.__module__ != 'builtins':
+ name = "{}.{}".format(type_.__module__, name)
+
+ self.__doc__ = self.__doc__ + "\n\n:type: :class:`{}`".format(name)
+
+
+class FieldRenderFormatStringMixin:
+ _FORMAT_STRING = None
+
+ def _render_value(self, value):
+ retval = self._FORMAT_STRING.format(value)
+ self._check_value_length(retval)
+
+ return retval
+
+
+class FixedLengthMixin:
+ _FIXED_LENGTH = [None, None, None]
+ _DOC_TYPE = str
+
+ def __init__(self, *args, **kwargs):
+ for i, a in enumerate(('length', 'min_length', 'max_length')):
+ kwargs[a] = self._FIXED_LENGTH[i] if len(self._FIXED_LENGTH) > i else None
+
+ super().__init__(*args, **kwargs)
+
+
+class ShortReprMixin:
+ def __repr__(self):
+ return "{}{}({})".format(
+ "{}.".format(self.__class__.__module__),
+ self.__class__.__name__,
+ ", ".join(
+ ("{!r}".format(value) if not name.startswith("_") else "{}={!r}".format(name, value))
+ for (name, value) in self._repr_items
+ )
+ )
+
+ def print_nested(self, stream=None, level=0, indent=" ", prefix="", first_level_indent=True, trailer=""):
+ stream.write(
+ ( (prefix + level*indent) if first_level_indent else "")
+ + "{!r}{}\n".format(self, trailer)
+ )
+
+
class MT535_Miniparser:
re_identification = re.compile(r"^:35B:ISIN\s(.*)\|(.*)\|(.*)$")
re_marketprice = re.compile(r"^:90B::MRKT\/\/ACTU\/([A-Z]{3})(\d*),{1}(\d*)$")