Commits

Lynn Rees committed a74329e

- work

  • Participants
  • Parent commits bad861e
  • Branches pu

Comments (0)

Files changed (7)

twoq/mixins/mapping.py

 
     '''repetition mixin'''
 
+    ###########################################################################
+    ## everything #############################################################
+    ###########################################################################
+
     def copy(self):
-        '''copy each incoming thing'''
-        return self._xinmap(deepcopy)
+        '''copy incoming things'''
+        return self._pre()._append(deepcopy(self._iterable))
 
     def padnone(self):
         '''repeat incoming things and then `None` indefinitely'''
         @param stop: number to stop with (default: 0)
         @param step: number of steps to advance per iteration (default: 1)
         '''
-        return self._pre()._extend(
+        return self._pextend(
             self._range(start, stop, step) if stop else self._range(start)
         )
 
         '''
         return self._inextend(lambda x: self._repeat(tuple(x), n))
 
-    def repeat_each(self, n):
-        '''
-        repeat each incoming thing `n` times
-
-        @param n: number of times to repeat each thing
-        '''
-        return self._pre()._xmap(
-            lambda x: self._repeat(x, n), self._inmap(tuple),
-        )
-
     def times(self, n=None):
         '''
         repeat call with incoming things `n` times
         @param n: repeat call n times on incoming things (default: None)
         '''
         if n is None:
-            return self._pre()._xstarmap(
-                self._call, self._repeat(self._list(self._iterable)),
+            return self._x2starmap(
+                self._call, lambda x: self._repeat(self._list(x)),
             )
-        return self._pre()._xstarmap(
-            self._call, self._repeat(self._list(self._iterable), n),
+        return self._x2starmap(
+            self._call, lambda x: self._repeat(self._list(x), n),
         )
 
+    ###########################################################################
+    ## each thing #############################################################
+    ###########################################################################
+
+    def copy_each(self):
+        '''copy each incoming thing'''
+        return self._xinmap(deepcopy)
+
+    def repeat_each(self, n):
+        '''
+        repeat each incoming thing `n` times
+
+        @param n: number of times to repeat each thing
+        '''
+        return self._pre()._x2map(lambda x: self._repeat(x, n), tuple)
+
     def times_each(self, n=None):
         '''
         repeat call with each incoming thing `n` times
         @param n: repeat call n times on incoming things (default: None)
         '''
         if n is None:
-            return self._pre()._xstarmap(
+            return self._xstarmap(
                 self._call, self._imap(self._repeat, self._inmap(self._list))
             )
-        return self._pre()._xstarmap(self._call, self._imap(
+        return self._xstarmap(self._call, self._imap(
             lambda x: self._repeat(x, n), self._inmap(self._list),
         ))
 
             self._call, self._ichain(self._inmap(self._items)),
         )
 
-    @classmethod
-    def exhaustmap(cls, mapr, call, filter=False, exception=StopIteration):
-        '''
-        call `next` on an iterator until it's exhausted
-
-        @param mapping: a mapping to exhaust
-        @param call: call to handle what survives the filter
-        @param filter: a filter to apply to mapping (default: `None`)
-        @param exception: exception sentinel (default: `StopIteration`)
-        '''
-        next_, starmap_ = cls._next, cls._starmap
-        subiter = cls._ifilter(
-            filter, cls._items(mapr)
-        ) if filter else cls._items(mapr)
-        try:
-            while 1:
-                next_(starmap_(call, subiter))
-        except exception:
-            pass
-
 
 class MappingMixin(DelayMixin, RepeatMixin, MapMixin):
 

twoq/mixins/ordering.py

     _sample = lazier(sample)
     _shuffle = lazier(shuffle)
 
-    ###########################################################################
-    ## all ####################################################################
-    ###########################################################################
-
     @classmethod
     def _shuffleit(cls, iterable):
-        '''shuffle an iterable'''
+        '''
+        shuffle iterable
+
+        @param iterable: an iterable
+        '''
         iterable = cls._list(iterable)
         cls._shuffle(iterable)
         return iterable
 
+    ###########################################################################
+    ## everything #############################################################
+    ###########################################################################
+
     def choice(self):
         '''random choice of/from incoming things'''
         return self._inappend(lambda x: self._choice(self._list(x)))
         return self._inextend(self._shuffleit)
 
     ###########################################################################
-    ## each ###################################################################
+    ## each thing #############################################################
     ###########################################################################
 
     def choice_each(self):
         '''choose random thing from each incoming thing'''
-        return self._xmap(self._choice, self._inmap(self._list))
-
-    def shuffle_each(self):
-        '''randomly order each incoming things'''
-        return self._xinmap(self._shuffleit)
+        return self._x2map(self._choice, self._list)
 
     def sample_each(self, n):
         '''
 
         @param n: number of samples
         '''
-        return self._xmap(self._sample, self._inmap(self._list))
+        return self._x2map(lambda x: self._sample(x, n), self._list)
+
+    def shuffle_each(self):
+        '''randomly order each incoming things'''
+        return self._xinmap(self._shuffleit)
 
 
 class OrderMixin(local):
 
     _groupby = lazier(groupby)
 
+    ###########################################################################
+    ## all ####################################################################
+    ###########################################################################
+
     def group(self):
         '''
         group incoming things, optionally using current call for key function
         call_, list_ = self._call, self._list
         if call_ is None:
             return self._pre()._extend(self._imap(
-                lambda x: [x[0], list_(x[1])],
-                self._groupby(self._iterable),
+                lambda x: [x[0], list_(x[1])], self._groupby(self._iterable),
             ))
         return self._pre()._extend(self._imap(
-            lambda x: [x[0], list_(x[1])],
-            self._groupby(self._iterable, call_)
+            lambda x: [x[0], list_(x[1])], self._groupby(self._iterable, call_)
         ))
 
-    def group_each(self):
-        '''
-        group each incoming thing, optionally using current call for key
-        function
-        '''
-        call_, groupby_ = self._call, self._groupby
-        if call_ is None:
-            return self._xmap(
-                lambda x: [x[0], self._list(x[1])], self._inmap(groupby_)
-            )
-        return self._xmap(
-            lambda x: [x[0], self._list(x[1])],
-            self._inmap(lambda x: groupby_(x, call_))
-        )
-
     def grouper(self, n, fill=None):
         '''
         split incoming things into sequences of length `n`, using `fill` thing
         @param n: number of things
         @param fill: fill thing (default: None)
         '''
-        return self._pre()._extend(
-            zip_longest(fillvalue=fill, *[self._iter(self._iterable)] * n)
+        iter_ = self._iter
+        return self._inextend(
+            lambda x: zip_longest(fillvalue=fill, *[iter_(x)] * n)
         )
 
     def reverse(self):
         list_, reversed_ = self._list, self._reversed
         return self._inextend(lambda x: reversed_(list_(x)))
 
-    def reverse_each(self):
-        '''reverse each incoming thing'''
-        return self._xinmap(self._reversed)
-
     def sort(self):
         '''
         sort incoming things, optionally using current call as key function
             return self._inextend(sorted_)
         return self._inextend(lambda x: sorted_(x, key=call_))
 
+    ###########################################################################
+    ## each ###################################################################
+    ###########################################################################
+
+    def group_each(self):
+        '''
+        group each incoming thing, optionally using current call for key
+        function
+        '''
+        call_, list_, groupby_ = self._call, self._list, self._groupby
+        if call_ is None:
+            return self._x2map(lambda x: [x[0], list_(x[1])], groupby_)
+        return self._xmap(
+            lambda x: [x[0], list_(x[1])], iter(lambda x: groupby_(x, call_))
+        )
+
+    def reverse_each(self):
+        '''reverse each incoming thing'''
+        return self._xinmap(self._reversed)
+
     def sort_each(self):
         '''
         sort each incoming thing, optionally using current call as key

twoq/mixins/queuing.py

         '''if queues are balanced'''
         return self.outcount() == self.__len__()
 
+    def ahead(self, n=None):
+        '''
+        move iterator for incoming things `n`-steps ahead
+
+        If `n` is `None`, consume entirely.
+
+        @param n: number of steps to advance incoming things (default: None)
+        '''
+        # use functions that consume iterators at C speed.
+        if n is None:
+            # feed the entire iterator into a zero-length `deque`
+            self.incoming = self._deek(self.incoming, maxlen=0)
+        else:
+            # advance to the empty slice starting at position `n`
+            self._next(self._islice(self.incoming, n, n), None)
+        return self
+
     ###########################################################################
     ## queue clearance ########################################################
     ###########################################################################
     ## queue rotation #########################################################
     ###########################################################################
 
-    def ahead(self, n=None):
-        '''
-        move iterator for incoming things `n`-steps ahead
-
-        If `n` is `None`, consume entirely.
-
-        @param n: number of steps to advance incoming things (default: None)
-        '''
-        # use functions that consume iterators at C speed.
-        if n is None:
-            # feed the entire iterator into a zero-length `deque`
-            self.incoming = self._deek(self.incoming, maxlen=0)
-        else:
-            # advance to the empty slice starting at position `n`
-            self._next(self._islice(self.incoming, n, n), None)
-        return self
-
     def reup(self):
         '''put incoming things in incoming things as one incoming thing'''
         return self.ctx1()._pre()._append(list(self._iterable)).unswap()
     def _inappend(self, call):
         return self._pre()._append(call(self._iterable))
 
+    def _pappend(self, iterable):
+        return self._pre()._append(iterable)
+
     def _amap(self, call, iterable):
         return self._pre()._append(self._imap(call, iterable))
 
     def _ainmap(self, call):
         return self._pre()._append(self._imap(call, self._iterable))
 
+    def _a2map(self, call1, call2):
+        imap_ = self._imap
+        return self._pre()._append(imap_(call1, imap_(call2, self._iterable)))
+
     def _ainstarmap(self, call):
         return self._pre()._append(self._starmap(call, self._iterable))
 
     ## queue extension ########################################################
     ###########################################################################
 
+    def _x2map(self, call1, call2):
+        imap_ = self._imap
+        return self._pre()._extend(imap_(call1, imap_(call2, self._iterable)))
+
     def _xreduce(self, call, initial=None):
         '''
         reduce iterable and extend outgoing things with results
             self._ireduce(call, self._iterable, initial)
         )
 
+    def _pextend(self, iterable):
+        return self._pre()._extend(iterable)
+
     def _inextend(self, call):
         return self._pre()._extend(call(self._iterable))
 
     def _xstarmap(self, call, iterable):
         return self._pre()._extend(self._starmap(call, iterable))
 
+    def _x2starmap(self, call, iterable):
+        return self._pre()._extend(
+            self._starmap(call, iterable(self._iterable))
+        )
+
     def _xinmap(self, call):
         return self._pre()._extend(self._imap(call, self._iterable))
 
         except exception:
             pass
 
+    @classmethod
+    def exhaustmap(cls, mapr, call, filter=False, exception=StopIteration):
+        '''
+        call `next` on an iterator until it's exhausted
+
+        @param mapping: a mapping to exhaust
+        @param call: call to handle what survives the filter
+        @param filter: a filter to apply to mapping (default: `None`)
+        @param exception: exception sentinel (default: `StopIteration`)
+        '''
+        next_, starmap_ = cls._next, cls._starmap
+        subiter = cls._ifilter(
+            filter, cls._items(mapr)
+        ) if filter else cls._items(mapr)
+        try:
+            while 1:
+                next_(starmap_(call, subiter))
+        except exception:
+            pass
+
     @staticmethod
     def iterexcept(call, exception, start=None):
         '''

twoq/tests/mixins/auto/mapping.py

 
 class ARepeatQMixin(object):
 
+    ###########################################################################
+    ## everything #############################################################
+    ###########################################################################
+
     def test_range(self):
         self.assertEqual(self.qclass().range(3).end(), [0, 1, 2])
         self.assertEqual(self.qclass().range(1, 3).end(), [1, 2])
             [[40, 50, 60], [40, 50, 60], [40, 50, 60]],
         )
 
-    def test_copy(self):
+    ###########################################################################
+    ## each thing #############################################################
+    ###########################################################################
+
+    def test_copy_each(self):
         testlist = [[1, [2, 3]], [4, [5, 6]]]
-        newlist = self.qclass(testlist).copy().end()
+        newlist = self.qclass(testlist).copy_each().end()
         self.assertFalse(newlist is testlist)
         self.assertListEqual(newlist, testlist)
         self.assertFalse(newlist[0] is testlist[0])
         self.assertFalse(newlist[1] is testlist[1])
         self.assertListEqual(newlist[1], testlist[1])
 
+    def test_repeat_each(self):
+        self.assertEqual(
+            [list(i) for i in self.qclass(
+                [40, 50, 60], [40, 50, 60]
+            ).repeat_each(3).end()],
+            [[(40, 50, 60), (40, 50, 60), (40, 50, 60)],
+            [(40, 50, 60), (40, 50, 60), (40, 50, 60)]],
+        )
+
+    def test_times_each(self):
+        def test(*args):
+            return list(args)
+        self.assertEqual(
+            [list(i) for i in self.qclass(
+                [40, 50, 60], [40, 50, 60]
+            ).tap(test).times_each(3).end()],
+            [[[40, 50, 60], [40, 50, 60], [40, 50, 60]],
+            [[40, 50, 60], [40, 50, 60], [40, 50, 60]]],
+        )
+
 
 class ADelayQMixin(object):
 

twoq/tests/mixins/auto/ordering.py

 
 class ARandomQMixin(object):
 
+    ###########################################################################
+    ## everything #############################################################
+    ###########################################################################
+
     def test_choice(self):
         self.assertEqual(len(list(self.qclass(1, 2, 3, 4, 5, 6).choice())), 1)
 
             len([5, 4, 6, 3, 1, 2]),
         )
 
+    ###########################################################################
+    ## each thing #############################################################
+    ###########################################################################
+
+    def test_choice_each(self):
+        self.assertEqual(len(list(
+            self.qclass([1, 2, 3], [4, 5, 6]).choice_each())),
+            2
+        )
+
+    def test_sample_each(self):
+        autoq = self.qclass([1, 2, 3], [4, 5, 6]).sample_each(2).end()
+        self.assertEqual(len(autoq), 2)
+        self.assertEqual(len(autoq[0]), 2)
+        self.assertEqual(len(autoq[1]), 2)
+
+    def test_shuffle_each(self):
+        autoq = self.qclass([1, 2, 3], [4, 5, 6]).shuffle_each().end()
+        self.assertEqual(len(autoq), 2)
+        self.assertEqual(len(autoq[0]), 3)
+        self.assertEqual(len(autoq[1]), 3)
+
 
 class AOrderQMixin(ARandomQMixin):
 
     '''combination mixin'''
 
+    ###########################################################################
+    ## everything #############################################################
+    ###########################################################################
+
     def test_group(self,):
         from math import floor
         self.assertEqual(
              [('moe', 'larry'), ('curly', 30), (40, 50), (True, 'x')]
         )
 
-    def test_reversed(self):
+    def test_reverse(self):
         self.assertEqual(
             self.qclass(5, 4, 3, 2, 1).reverse().end(), [1, 2, 3, 4, 5],
         )
             [2, 3, 4, 4, 6, 63, 65],
         )
 
+    ###########################################################################
+    ## each thing #############################################################
+    ###########################################################################
+
+#    def test_group_each(self,):
+#        self.assertEqual(
+#            self.qclass([1.3, 2.1, 2.4], [1.3, 2.1, 2.4]).group_each().end(),
+#            [[1.3, [1.3]], [2.1, [2.1]], [2.4, [2.4]]],
+#            [[1.3, [1.3]], [2.1, [2.1]], [2.4, [2.4]]],
+#        )
+#        from math import floor
+#        self.assertEqual(
+#        self.qclass([1.3, 2.1, 2.4], [1.3, 2.1, 2.4]).tap(
+#            lambda x: floor(x)
+#        ).group_each().end(),
+#            [[[1.3, [1.3]], [2.1, [2.1]], [2.4, [2.4]]],
+#            [[1.3, [1.3]], [2.1, [2.1]], [2.4, [2.4]]]]
+#        )
+
+    def test_reverse_each(self):
+        self.assertEqual(
+            list(list(i) for i in self.qclass(
+                [5, 4, 3, 2, 1], [5, 4, 3, 2, 1]
+            ).reverse_each().tap(list).end()),
+            [[1, 2, 3, 4, 5], [1, 2, 3, 4, 5]],
+        )
+
+    def test_sort_each(self):
+        from math import sin
+        self.assertEqual(
+            self.qclass([1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6]).tap(
+                lambda x: sin(x)
+            ).sort_each().end(),
+            [[5, 4, 6, 3, 1, 2], [5, 4, 6, 3, 1, 2]],
+        )
+        self.assertEqual(
+            self.qclass(
+                [4, 6, 65, 3, 63, 2, 4], [4, 6, 65, 3, 63, 2, 4]
+            ).sort_each().end(),
+            [[2, 3, 4, 4, 6, 63, 65], [2, 3, 4, 4, 6, 63, 65]],
+        )
+
 
 __all__ = sorted(name for name, obj in port.items(locals()) if not any([
     name.startswith('_'), ismodule(obj), name in ['ismodule', 'port']

twoq/tests/mixins/man/mapping.py

             [[40, 50, 60], [40, 50, 60], [40, 50, 60]],
         )
 
-    def test_copy(self):
+    def test_copy_each(self):
         testlist = [[1, [2, 3]], [4, [5, 6]]]
-        manq = self.qclass(testlist).copy()
+        manq = self.qclass(testlist).copy_each()
         self.assertTrue(manq.balanced)
         manq.sync()
         self.assertTrue(manq.balanced)

twoq/tests/mixins/man/ordering.py

 
 class MRandomQMixin(object):
 
+    ###########################################################################
+    ## everything #############################################################
+    ###########################################################################
+
     def test_choice(self):
         manq = self.qclass(1, 2, 3, 4, 5, 6).choice()
         self.assertFalse(manq.balanced)
         manq.end()
         self.assertTrue(manq.balanced)
 
+    ###########################################################################
+    ## each thing #############################################################
+    ###########################################################################
+
+#    def test_choice_each(self):
+#        manq = self.qclass([1, 2, 3], [4, 5, 6]).choice_each()
+#        self.assertFalse(manq.balanced)
+#        manq.sync()
+#        self.assertTrue(manq.balanced)
+#        manq.end()
+#        self.assertTrue(manq.balanced)
+#
+#    def test_sample_each(self):
+#        manq = self.qclass([1, 2, 3], [4, 5, 6]).sample_each(2)
+#        self.assertFalse(manq.balanced)
+#        manq.sync()
+#        self.assertTrue(manq.balanced)
+#        manq.end()
+#        self.assertTrue(manq.balanced)
+#
+#    def test_shuffle_each(self):
+#        manq = self.qclass([1, 2, 3], [4, 5, 6]).shuffle()
+#        self.assertTrue(manq.balanced)
+#        manq.sync()
+#        self.assertTrue(manq.balanced)
+#        manq.end()
+#        self.assertTrue(manq.balanced)
+
 
 class MOrderQMixin(MRandomQMixin):