33b5e3151ac6 draft — Loic Balland tip 12 days ago
strip function exposed on the api layer
2 files changed, 75 insertions(+), 2 deletions(-)

M test/test_api.py
M tshistory/api.py
M test/test_api.py +56 -2
@@ 1,9 1,10 @@ 
 from datetime import timedelta, datetime as dt
-import pandas as pd
 import pytest
 
+import pandas as pd
+import numpy as np
+
 from tshistory.api import timeseries
-
 from tshistory.testutil import (
     assert_df,
     assert_hist,

          
@@ 626,6 627,59 @@ 2019-01-03 00:00:00+00:00    3.0
     assert tsa.type('autotrophic') == 'formula'
 
 
+def test_strip(pgapi):
+    tsa = pgapi
+
+    for i in range(3):
+        ts = pd.Series(
+            np.array([1, 2, 3]) + i,
+            pd.date_range(utcdt(2021, 1, 1), freq='D', periods=3)
+        )
+        tsa.update(
+            'stripme',
+            ts,
+            'Babar',
+            insertion_date=utcdt(2021, 1, 1+i)
+        )
+
+    revs = tsa.insertion_dates('stripme')
+    assert revs == [
+        pd.Timestamp('2021-01-01 00:00:00+0000', tz='UTC'),
+        pd.Timestamp('2021-01-02 00:00:00+0000', tz='UTC'),
+        pd.Timestamp('2021-01-03 00:00:00+0000', tz='UTC')
+    ]
+
+    # in the future: a noop
+    tsa.strip('stripme', utcdt(2021, 1, 31))
+    revs = tsa.insertion_dates('stripme')
+    assert len(revs) == 3
+
+    # remove two
+    tsa.strip('stripme', utcdt(2021, 1, 2))
+    revs = tsa.insertion_dates('stripme')
+    assert revs == [
+        pd.Timestamp('2021-01-01 00:00:00+0000', tz='UTC'),
+    ]
+
+    # wipe all
+    tsa.strip('stripme', utcdt(2021, 1, 1))
+    revs = tsa.insertion_dates('stripme')
+    assert revs == []
+
+    ts = pd.Series(
+        [1, 2, 3],
+        pd.date_range(utcdt(2021, 1, 1), freq='D', periods=3)
+    )
+    # now this is interesting ... tsh.interval wants at least a revision
+    with pytest.raises(AttributeError):
+        tsa.update(
+            'stripme',
+            ts,
+            'Babar',
+            insertion_date=utcdt(2021, 1, 10)
+        )
+
+
 def test_conflicting_update(mapi):
     # behaviour when a series exists locally and remotely
     mapi.update(

          
M tshistory/api.py +19 -0
@@ 455,6 455,25 @@ class dbtimeseries:
         return self.tsh.delete(self.engine, name)
 
 
+    def strip(self, name: str, insertion_date: datetime) -> None:
+        """Remove revisions after a specific insertion date.
+
+        This is an irreversible operation.
+
+        """
+
+        insertion_date = ensuretz(insertion_date)
+        if not self.tsh.exists(self.engine, name):
+            raise Exception(f'no series {name} exists')
+
+        with self.engine.begin() as cn:
+            csid = self.tsh.changeset_at(
+                cn, name, insertion_date, 'after'
+            )
+            if csid is not None:
+                return self.tsh.strip(cn, name, csid)
+
+
 class source:
     __slots__ = 'uri', 'namespace', 'tsa'