# HG changeset patch # User Loic Balland # Date 1613498115 -3600 # Tue Feb 16 18:55:15 2021 +0100 # Node ID 33b5e3151ac6842a2ace1f5538ab09191695b170 # Parent fdc7cfa0262e48dfa114f3bcca7270fb4417f357 strip function exposed on the api layer diff --git a/test/test_api.py b/test/test_api.py --- a/test/test_api.py +++ b/test/test_api.py @@ -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 @@ 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( diff --git a/tshistory/api.py b/tshistory/api.py --- a/tshistory/api.py +++ b/tshistory/api.py @@ -455,6 +455,25 @@ 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'