From 57464b0621a19ba8ab9570bec42af8d141c2d95b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ma=C5=9Blanka?= <piotr.maslanka@henrietta.com.pl> Date: Tue, 1 Dec 2020 18:35:47 +0100 Subject: [PATCH] get_current_value added --- .circleci/config.yml | 2 +- .coveragerc | 15 +++++++++++++++ .gitignore | 2 +- README.md | 2 +- setup.py | 7 ++++--- tempsdb/iterators.pyx | 14 ++++++++++++++ tempsdb/series.pxd | 1 + tempsdb/series.pyx | 20 ++++++++++++++++++++ tests/test_db.py | 8 ++++++++ unittest.Dockerfile | 7 +++++-- 10 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 .coveragerc diff --git a/.circleci/config.yml b/.circleci/config.yml index 0a9101c..4fc7413 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,7 +17,7 @@ jobs: name: Install necessary modules - run: command: | - sudo python setup.py test + sudo coverage run setup.py test name: Test workflows: diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..001df73 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,15 @@ +[run] +branch=1 +plugins = Cython.Coverage +source= + tempsdb +concurrency=thread +omit= + tests/* + .eggs/* + setup.py + tempsdb/__init__.py + +[report] +include= + tempsdb/* diff --git a/.gitignore b/.gitignore index e51a134..791fd86 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ __pycache__/ # C extensions *.so - +tempsdb/__bootstrap__.pyx # Distribution / packaging .Python build/ diff --git a/README.md b/README.md index c1f28aa..4cbef08 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ So no variable encoding for you! ## v0.3 -* _TBA_ +* added `TimeSeries.get_current_value` ## v0.2 diff --git a/setup.py b/setup.py index 2014def..6a6ae85 100644 --- a/setup.py +++ b/setup.py @@ -19,15 +19,16 @@ def find_pyx(*path) -> tp.List[str]: # Extension('tempsdb.series', ['tempsdb/series.pyx']), # Extension('tempsdb.iterators', ['tempsdb/iterators.pyx'])] # +directives = {'language_level': '3'} +if 'CI' in os.environ: + directives.update(profile=True, linetrace=True) setup(name='tempsdb', version='0.3_a1', packages=['tempsdb'], install_requires=['satella>=2.14.21', 'ujson'], ext_modules=build([Multibuild('tempsdb', find_pyx('tempsdb')), ], - compiler_directives={ - 'language_level': '3', - }), + compiler_directives=directives), # ext_modules=cythonize(extensions, # gdb_debug=True, # compiler_directives={ diff --git a/tempsdb/iterators.pyx b/tempsdb/iterators.pyx index d94d670..9a0621b 100644 --- a/tempsdb/iterators.pyx +++ b/tempsdb/iterators.pyx @@ -8,6 +8,14 @@ cdef class Iterator: """ Iterator that allows iterating through result. + Can be used as a context manager: + + >>> with series.iterate_range(0, 5000) as it: + >>> for timestamp, value in it: + >>> ... + + It will close itself automatically. + At most basic this implements an iterator interface, iterating over tp.Tuple[int, bytes] - timestamp and data @@ -25,6 +33,12 @@ cdef class Iterator: self.is_first = False self.is_last = False + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + def __del__(self): self.close() diff --git a/tempsdb/series.pxd b/tempsdb/series.pxd index 57eda5d..fb80b3e 100644 --- a/tempsdb/series.pxd +++ b/tempsdb/series.pxd @@ -37,6 +37,7 @@ cdef class TimeSeries: cdef unsigned int get_index_of_chunk_for(self, unsigned long long timestamp) cpdef int trim(self, unsigned long long timestamp) except -1 cpdef unsigned long open_chunks_ram_size(self) + cpdef tuple get_current_value(self) cdef inline int get_references_for(self, unsigned long long timestamp): return self.refs_chunks.get(timestamp, 0) diff --git a/tempsdb/series.pyx b/tempsdb/series.pyx index 3bcff38..fe6e7f7 100644 --- a/tempsdb/series.pyx +++ b/tempsdb/series.pyx @@ -23,6 +23,26 @@ cdef class TimeSeries: :ivar name: name of the series (str) """ + cpdef tuple get_current_value(self): + """ + Return latest value of this series + + .. versionadded:: 0.3 + + :return: tuple of (timestamp, value) + :rtype: tp.Tuple[int, bytes] + :raises ValueError: series has no data + """ + if self.last_chunk is None: + raise ValueError('No data in series') + cdef: + Iterator it = self.iterate_range(self.last_chunk.max_ts, self.last_chunk.max_ts) + tuple tpl = it.next() + try: + return tpl + finally: + it.close() + def __init__(self, path: str, name: str, use_descriptor_based_access: bool = False): self.descriptor_based_access = use_descriptor_based_access self.mpm = None diff --git a/tests/test_db.py b/tests/test_db.py index 29f19e9..4e24666 100644 --- a/tests/test_db.py +++ b/tests/test_db.py @@ -10,6 +10,14 @@ class TestDB(unittest.TestCase): series = create_series('test3', 'test3', 10, 4096) for i in range(8000): series.append(i, b'\x00'*10) + + self.assertEqual(series.get_current_value(), (i, b'\x00'*10)) + + with series.iterate_range(i, i) as it: + lst = list(it) + self.assertEqual(len(lst), 1) + self.assertEqual(lst[0][0], i) + series.trim(4100) self.assertEqual(len(os.listdir('test3')), 2) diff --git a/unittest.Dockerfile b/unittest.Dockerfile index 8d69b7f..c567def 100644 --- a/unittest.Dockerfile +++ b/unittest.Dockerfile @@ -1,13 +1,16 @@ FROM python:3.8 -RUN pip install satella snakehouse nose2 wheel ujson +RUN pip install satella snakehouse nose2 wheel ujson coverage ADD tempsdb /app/tempsdb ADD setup.py /app/setup.py +ADD .coveragerc /app/.coveragerc ADD setup.cfg /app/setup.cfg WORKDIR /app + +ENV CI=true RUN python setup.py build_ext --inplace ADD tests /app/tests -CMD ["nose2", "-vv"] +CMD ["coverage", "run", "-m", "nose2", "-vv"] -- GitLab