From 2663a5582ce17f9450cdb6ffb3d711b1e22d1500 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Mat=C4=9Bjka?= <jan@matejka.ninja>
Date: Thu, 30 Jan 2025 21:07:24 +0100
Subject: [PATCH] refactor(message-queue/python): SampleIterator

its ugly but its an interesting question of 1. if genrator or iterator is
preferred. 2. why is not working.
---
 message-queue/python/src/jmcgmqp/algorithm.py | 44 +++++++++++++++++++
 message-queue/python/test/test_algorithm.py   | 16 +++++--
 2 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/message-queue/python/src/jmcgmqp/algorithm.py b/message-queue/python/src/jmcgmqp/algorithm.py
index b68b916c..9416338c 100644
--- a/message-queue/python/src/jmcgmqp/algorithm.py
+++ b/message-queue/python/src/jmcgmqp/algorithm.py
@@ -1,3 +1,4 @@
+from collections.abc import Iterator
 from dataclasses import dataclass
 from typing import *
 import itertools
@@ -5,6 +6,49 @@
 T = TypeVar('T')
 Sampler = Callable[[int],[T]]
 
+@dataclass
+class SampleIterator(Iterator):
+    sampler: Sampler
+    i:int = 0
+
+    _prev:T | None = None
+
+    def __post_init__(self):
+        print(self.__next__)
+        print(self._next_power)
+        self.__next__ = self._next_power
+        print(self.__next__)
+
+    def __next__(self):
+        ... # pragma: nocover this is here only to satisfy the interface.
+        print("what")
+
+    def _next_power(self):
+        print("power")
+        r = self.sampler(2**self.i)
+        print(r)
+        if prev and prev >= r:
+            self.__next__ = self._next_step
+            self.i -= 1
+        else:
+            self.i += 1
+        return r
+
+    def _next_step(self):
+        print("step")
+        self.i += 1
+        r = self.sampler(self.i)
+        if prev and prev >= r:
+            self.__next__ = self._next_stop
+        return r
+
+    def _next_stop(self):
+        print("stop")
+        raise StopIteration()
+
+    def __iter__(self):
+        return self
+
 def SampleGenerator(
     sample: Sampler,
     starting_power: int = 0,
diff --git a/message-queue/python/test/test_algorithm.py b/message-queue/python/test/test_algorithm.py
index 5081362b..fbc659b3 100644
--- a/message-queue/python/test/test_algorithm.py
+++ b/message-queue/python/test/test_algorithm.py
@@ -1,18 +1,28 @@
-from jmcgmqp.algorithm import find_maximum, Sampler
+from jmcgmqp.algorithm import find_maximum, Sampler, SampleIterator
 
 from unittest.mock import create_autospec, call
 import pytest
 
-@pytest.mark.parametrize('sequence, result, args, power', (
+cases = (
     ((1, 1, 1), 1, (1, 2), 0),
     ((1, 2, 1, 1), 2, (1, 2, 4, 3), 0),
     ((1, 2, 1, 3), 3, (1, 2, 4, 3), 0),
     ((1, 2, 3, 4, 5, 1, 1), 5, (1, 2, 4, 8, 16, 32, 17), 0),
     ((1, 2, 3, 1, 4, 5, 1), 5, (1, 2, 4, 8, 5, 6, 7), 0),
     ((1, 1, 1), 1, (4, 8, 5), 2),
-))
+)
+
+@pytest.mark.parametrize('sequence, result, args, power', cases)
 def test_find_maximum(sequence, result, args, power):
     sample = create_autospec(Sampler, spec_set=True)
     sample.side_effect = sequence
     assert find_maximum(sample, power) == result
     assert sample.call_args_list == [call(x) for x in args]
+
+@pytest.mark.parametrize('sequence, result, args, power', cases)
+def test_SampleIterator(sequence, result, args, power):
+    sample = create_autospec(Sampler, spec_set=True)
+    sample.side_effect = sequence
+    assert next(SampleIterator(sample, power)) == args[0]
+    return
+    assert tuple(SampleIterator(sample, power)) == args