|
3 | 3 | from contextlib import suppress |
4 | 4 | from inspect import getmro |
5 | 5 | from copy import deepcopy |
6 | | -from collections import OrderedDict |
| 6 | +from collections import OrderedDict, Iterable |
7 | 7 |
|
8 | 8 | from fints.utils import classproperty, SubclassesMixin, Password |
9 | 9 |
|
@@ -392,11 +392,42 @@ def find_segments(self, type=None, version=None, callback=None, recurse=True): |
392 | 392 | The match results of all given parameters will be AND-combined. |
393 | 393 | """ |
394 | 394 |
|
| 395 | + if type is None: |
| 396 | + type = [] |
| 397 | + elif isinstance(type, str) or not isinstance(type, (list, tuple, Iterable)): |
| 398 | + type = [type] |
| 399 | + |
| 400 | + if version is None: |
| 401 | + version = [] |
| 402 | + elif not isinstance(version, (list, tuple, Iterable)): |
| 403 | + version = [version] |
| 404 | + |
| 405 | + if callback is None: |
| 406 | + callback = lambda s: True |
| 407 | + |
| 408 | + for s in self.segments: |
| 409 | + if ((not type) or any(s.header.type == t for t in type)) and \ |
| 410 | + ((not version) or any(s.header.version == v for v in version)) and \ |
| 411 | + callback(s): |
| 412 | + yield s |
| 413 | + |
| 414 | + if recurse: |
| 415 | + for name, field in s._fields.items(): |
| 416 | + if isinstance(field, SegmentSequenceField): |
| 417 | + val = getattr(s, name) |
| 418 | + if val: |
| 419 | + yield from val.find_segments(type=type, version=version, callback=callback, recurse=recurse) |
| 420 | + |
395 | 421 | def find_segment_first(self, *args, **kwargs): |
396 | 422 | """Finds the first matching segment. |
397 | 423 |
|
398 | 424 | Same parameters as find_segments(), but only returns the first match, or None if no match is found.""" |
399 | 425 |
|
| 426 | + for m in self.find_segments(*args, **kwargs): |
| 427 | + return m |
| 428 | + |
| 429 | + return None |
| 430 | + |
400 | 431 | class SegmentSequenceField(DataElementField): |
401 | 432 | type = 'sf' |
402 | 433 |
|
|
0 commit comments