src/pyams_utils/list.py
changeset 337 d4e617c7e37a
parent 292 b338586588ad
child 380 c062ab4db6cd
equal deleted inserted replaced
336:5aa846ce2a2d 337:d4e617c7e37a
    10 # FOR A PARTICULAR PURPOSE.
    10 # FOR A PARTICULAR PURPOSE.
    11 #
    11 #
    12 
    12 
    13 __docformat__ = 'restructuredtext'
    13 __docformat__ = 'restructuredtext'
    14 
    14 
    15 
    15 from itertools import filterfalse, tee
    16 # import standard library
       
    17 from itertools import filterfalse
       
    18 from random import random, shuffle
    16 from random import random, shuffle
    19 
    17 
    20 # import interfaces
    18 from zope.interface import Interface
    21 
    19 
    22 # import packages
    20 from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config
       
    21 from pyams_utils.interfaces.tales import ITALESExtension
    23 
    22 
    24 
    23 
    25 def unique(seq, key=None):
    24 def unique(seq, key=None):
    26     """Extract unique values from list, preserving order
    25     """Extract unique values from list, preserving order
    27 
    26 
   121             selected_index = int(random() * (index+1))
   120             selected_index = int(random() * (index+1))
   122             if selected_index < limit:
   121             if selected_index < limit:
   123                 selected[selected_index] = item
   122                 selected[selected_index] = item
   124     shuffle(selected)
   123     shuffle(selected)
   125     return iter(selected)
   124     return iter(selected)
       
   125 
       
   126 
       
   127 def boolean_iter(iterable):
       
   128     """Check if an iterable returns at least one value, without consuming it.
       
   129 
       
   130     The function returns a tuple containing a boolean flag indicating if the original iterator
       
   131     is empty or not, and the original un-consumed iterator.
       
   132 
       
   133     >>> from pyams_utils.list import boolean_iter
       
   134     >>> def empty(input):
       
   135     ...     yield from input
       
   136     >>> mylist = empty(())
       
   137     >>> check, myiter = boolean_iter(mylist)
       
   138     >>> check
       
   139     False
       
   140     >>> list(myiter)
       
   141     []
       
   142     >>> mylist = empty((1,2,3))
       
   143     >>> check, myiter = boolean_iter(mylist)
       
   144     >>> check
       
   145     True
       
   146     >>> list(myiter)
       
   147     [1, 2, 3]
       
   148     >>> list(myiter)
       
   149     []
       
   150     """
       
   151 
       
   152     def inner_check():
       
   153         check, items = tee(iterable)
       
   154         try:
       
   155             next(check)
       
   156         except StopIteration:
       
   157             yield False
       
   158         else:
       
   159             yield True
       
   160             yield from items
       
   161 
       
   162     values = inner_check()
       
   163     return next(values), values
       
   164 
       
   165 
       
   166 @adapter_config(name='boolean_iter', context=(Interface, Interface, Interface), provides=ITALESExtension)
       
   167 class IterValuesCheckerExpression(ContextRequestViewAdapter):
       
   168     """TALES expression used to handle iterators
       
   169 
       
   170     The expression returns a tuple containing a boolean flag indicating if the original iterator
       
   171     is empty or not, and the original un-consumed iterator.
       
   172     """
       
   173 
       
   174     def render(self, context=None):
       
   175         if context is None:
       
   176             context = self.context
       
   177         return boolean_iter(context)