From 6f7d77b1f6220f97a1b8579273c30bf5ce66ef0b Mon Sep 17 00:00:00 2001
From: beckerfy <fynn.becker@hs-hannover.de>
Date: Tue, 9 Jun 2020 13:46:31 +0200
Subject: [PATCH] Close #10 Add caching when using unbounded slices

---
 postgrestutils/client/postgrestclient.py |  5 +++++
 tests/test_postgrestclient.py            | 23 +++++++++++++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/postgrestutils/client/postgrestclient.py b/postgrestutils/client/postgrestclient.py
index 79dbfde..0c08753 100644
--- a/postgrestutils/client/postgrestclient.py
+++ b/postgrestutils/client/postgrestclient.py
@@ -130,10 +130,15 @@ class LazyPostgrestJsonResult:
         if isinstance(key, slice) and key.step is not None:
             raise ValueError("{self.__class__.__name__} does not support stepping".format(self=self))
 
+        # cache is not populated and unbounded slice is requested, i.e. res[:]
+        if isinstance(key, slice) and all(e is None for e in (self._result_cache, key.start, key.stop)):
+            self._fetch_all()
+
         if self._result_cache is not None:
             return self._result_cache[key]
 
         if isinstance(key, slice):
+
             range = '{start}-{stop}'.format(
                 start=key.start or 0,
                 stop=key.stop and key.stop - 1 or ''
diff --git a/tests/test_postgrestclient.py b/tests/test_postgrestclient.py
index 1cb39c8..99e2d48 100644
--- a/tests/test_postgrestclient.py
+++ b/tests/test_postgrestclient.py
@@ -226,6 +226,29 @@ class TestPgrestClientFilterStrategyNone(TestCase):
         self.assertListEqual(list(res), self.data)  # should utilize cache
         self.assertTrue(mock.called_once)  # should not have been called again
 
+    def test_cache_fetching_unbounded_slice(self, mock):
+        mock.register_uri(
+            'GET',
+            'http://example.com/superhero',
+            request_headers=DEFAULT_HEADERS,
+            status_code=200,
+            reason='OK',
+            json=self.data
+        )
+        res = self.pgrest_client.filter('superhero')
+
+        self.assertIsInstance(res, LazyPostgrestJsonResult)  # should return lazy object
+        self.assertFalse(mock.called)  # no request should have been made yet
+
+        self.assertListEqual(res[:], self.data)  # fetch data
+        self.assertTrue(mock.called_once)  # should have been called once
+        self.assertListEqual(res._result_cache, self.data)  # fetched data should be cached
+        self.assertEqual(res._len_cache, len(self.data))  # len of fetched data should be cached
+        self.assertListEqual(res[:], self.data)  # should utilize cache
+        self.assertListEqual(res[2:], self.data[2:])  # should utilize cache
+        self.assertDictEqual(res[0], self.data[0])  # should utilize cache
+        self.assertTrue(mock.called_once)  # should not have been called again
+
 
 @Mocker()
 class TestPgrestClientFilterStrategyExact(TestCase):
-- 
GitLab