Source code for itertree.itree_helpers

"""
This code is taken from the itertree package:
  _ _____ _____ _____ _____ _____ _____ _____
 | |_   _|   __| __  |_   _| __  |   __|   __|
 |-| | | |   __|    -| | | |    -|   __|   __|
 |_| |_| |_____|__|__| |_| |__|__|_____|_____|

https://pypi.org/project/itertree/
GIT Home:
https://github.com/BR1py/itertree
The documentation can be found here:
https://itertree.readthedocs.io/en/latest/index.html

The code is published under MIT license
For more information see: https://en.wikipedia.org/wiki/MIT_License

CONTENT DESCRIPTION:

This part of code contains
helper classes used in DataTree object
"""

from __future__ import absolute_import

import abc
import time
import os
import zlib
import fnmatch
import operator
import itertools
from collections import namedtuple, deque

try:
    #raise ImportError
    # This really recommended for faster operations!
    from blist import blist
    itree_list=blist

    BLIST_SWITCH = 100  # break even from which size on blist should be used instead of normal list
    BLIST_ACTIVE = True


except ImportError:
    # if not available we take normal list
    itree_list = list
    BLIST_ACTIVE = False
    BLIST_SWITCH = -1  # never

try:
    import numpy as np
except ImportError:
    np = None



[docs] def accu_iterator(iterable, accu_method, initial_value=(None,)): """ A method that enables itertools accumulation over a method .. note:: This method is just needed because in python <3.8 itertools accumulation has no initial parameter! :param iterable: iterable :param accu_method: accumulation method (will be fet by two parameters cumulated and new item) :return: accumulated iterator """ for i in iterable: initial_value = accu_method(initial_value, i) yield initial_value
[docs] def is_iterator_empty(iterator): ''' checks if the given iterator is empty :param iterator: iterator to be checked :rtype: tuple :return: * (True, iterator) - empty * (False, iterator) - item inside ''' try: i = next(iterator) except StopIteration: return True, iterator return False, itertools.chain((i,), iterator)
[docs] def rindex(lst, value): ''' find last occurance of a itme in the list :param lst: list :param value: search value :return: ''' lst.reverse() i = lst.index(value) lst.reverse() return len(lst) - i - 1
ORDER_PRE=1 ORDER_POST=0 ORDER_LEVEL=2
[docs] class iTFLAG(): """ public flags for setting the `iTree behavior during `__init__()` """ READ_ONLY_TREE = 0b1 READ_ONLY_VALUE = 0b10 LOAD_LINKS = 0b100
class _iTFLAG(): """ internal used flags (must not be used by the user!) """ LINKED = 0b1000 PLACEHOLDER = 0b10000 LINK_ROOT = 0b100000 FLAG_MASK = 0b111111 INF=float('inf') INF_PLUS=float('+inf') INF_MINUS=float('-inf')
[docs] class Any(object): """ Helper class used for marking that the ìTree()-object is "empty" no value is stored inside. If required use the class as it is, do not instance an object. """ def __init__(self): raise SyntaxError('The object cannot be instanced')
[docs] class NoValue(object): """ Helper class used for marking that the ìTree()-object is "empty" no value is stored inside. If required use the class as it is, do not instance an object. """ def __init__(self): raise SyntaxError('The object cannot be instanced')
[docs] class NoTag(object): # must be hashable! """ Helper class used for the NoTag-family tag which is automatically used in case no explicit tag is given during creation of the ìTree()-object. If required use the class as it is, do not instance an object. """ def __init__(self): raise SyntaxError('The object cannot be instanced')
[docs] class NoKey(object): # must be hashable! """ Helper class used for the NoKey entries in dicts stored as value object in the ìTree()-object. If required use the class as it is, do not instance an object. """ def __init__(self): raise SyntaxError('The object cannot be instanced')
[docs] class NoTarget(object): # must be hashable! """ Helper class used for the NoKey entries in dicts stored as value object in the ìTree()-object. If required use the class as it is, do not instance an object. """ def __init__(self): raise SyntaxError('The object cannot be instanced')
[docs] class ArgTuple(tuple): pass
[docs] class Tag(): """ Helper class used in get-methods for marking that the given value is a family-tag and not an index or key, etc. """ __slots__ = ['tag'] def __init__(self, tag=NoTag): self.tag = tag def __getitem__(self, key): return self.tag def __repr__(self): return 'Tag(%s)' % repr(self.tag) def __hash__(self): # We do not allow hashs of this object to avoid that it is used as tag of iTree objects raise TypeError("unhashable type: 'Tag'")
TagIdx = namedtuple('TagIdx',['tag','idx']) # For downward compatibility
[docs] def getter_to_list(get_result): """ Helper function that always creates a list from a `iTree`get-method result. 1. In case we have a iterator the list with the iterator items is created. 2. In case we have a single item a list [single_item] is created 3. In case we have no item or empty iterator an empty list is created. :param get_result: result coming from a getter method :rtype: list :return: result list """ if hasattr(get_result, '_itree_prt_idx'): return [get_result] else: return list(get_result)
[docs] class ITER(): """ iter options for deep iterators """ DOWN=0b1 #gives iteration direction top-> down (default) UP=DOWN <<1 # gives iteration direction bottom-> up # in case DOWN adn UP is in we use UP; # Both flags are just in because of downward compatibility REVERSE=UP<<1 # switches item iteration direction to high index -> low index SELF=REVERSE<<1 # include the calling object in the iteration (only if target matches) FILTER_ANY= SELF<<1 # Use build in filtering instead of hierarchical filtering (only in iter()) MULTIPLE=FILTER_ANY<<1 # allows multiple matches of items in an iteration
[docs] @staticmethod def get_option_str(option): """ calculates a string representing the options used in given option :para option: integer containing the option-bits :return: """ options=[] if option & ITER.DOWN: options.append('DOWN') if option&ITER.UP: options.append('UP') if option&ITER.REVERSE: options.append('REVERSE') if option&ITER.SELF: options.append('SELF') if option&ITER.FILTER_ANY: options.append('FILTER_ANY') if option & ITER.MULTIPLE: options.append('MULTIPLE') invalid=option&~(ITER.UP | ITER.REVERSE | ITER.SELF |ITER.FILTER_ANY |ITER.MULTIPLE) if invalid: options.append('%s'%bin(invalid)) return ' | '.join(options)
[docs] @staticmethod def valid_option(option,expected_option=DOWN |UP | REVERSE | SELF |FILTER_ANY |MULTIPLE): """ checks if given option is valid :para option: integer containing the options-bits :para expected_option: integer containing the full set of possible option-bits :return: None or string for exception containing the invalid flags used """ invalid=option&(~expected_option) if invalid: return 'Invalid iteration option(s) given: %s'%ITER.get_option_str(invalid)