From: Christian Herdtweck Date: Wed, 7 Dec 2016 10:21:47 +0000 (+0100) Subject: Create text_helper shortened(...) X-Git-Tag: v1.2~13 X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=d85022898c4b042c7486b87f3b1d92e8153426f8;p=pyi2ncommon Create text_helper shortened(...) --- diff --git a/src/text_helpers.py b/src/text_helpers.py index e055f20..d5e208f 100644 --- a/src/text_helpers.py +++ b/src/text_helpers.py @@ -27,7 +27,73 @@ except ImportError: # different name in py2 from __builtin__ import print as _builtin_print from functools import partial +from itertools import islice +from type_helpers import isstr + + +def shortened(iterable, n_head=20, n_tail=20, n_elems=None, + skip_elem="...(skipping {n_skipped} elements)..."): + """ convenient way to shorten a possibly very long iterable before printing + + Will not modify short iterables, but for longer lists/tuples/... will only + yield first few, then a message how many were skipped and the last few + + The iterable does not even have to have a `len(..)` method if argument + `n_elems` is given. Only needs a `next(..)` method. However, for very long + iterables this will be faster if radnom element access is provided via [] + + :param iterable: an iterable + :param int n_head: number of starting elements to yield (optional) + :param int n_tail: number of ending elements to yield (optional) + :param int n_elems: number of elements in iterable; give this to avoid a + call to `len(iterable)` (optional) + :param skip_elem: element to replace bulge of skipped elements; yielded + once at most; None to not yield a skip replacement; if str + then it will be formatted; optional, defaults to string + with number of skipped elems + + ..seealso: :py:func:`slice`, py:func:`itertools.islice` + """ + + if n_elems is None: + n_elems = len(iterable) + + # yield first n_head elems + index = 0 + for elem in iterable: + index += 1 + if index > n_head: + break + yield elem + + # yield skip element + if n_elems > n_head + n_tail: + if skip_elem is not None: + if (isstr(skip_elem)): + yield skip_elem.format(n_skipped=n_elems-n_head-n_tail) + else: + yield skip_elem + elif n_elems <= n_head: + raise StopIteration() + + # yield end + try: + # try to access end directly + for elem in iterable[n_elems-n_tail:]: + yield elem + except TypeError: + # if this did not work, then need to iterate through whole thing + # do this as in itertool recipe for consume(): + n_skip = n_elems - n_head - n_tail - 1 + next(islice(iterable, n_skip, n_skip), None) + for elem in iterable: + yield elem + + +############################################################################### +# TEXT FORMATTING/COLORING +############################################################################### COLOR_BLACK = 'black' COLOR_RED = 'red'