From 6aa0a90c3ad92fddb40c293fb8047997adb05e05 Mon Sep 17 00:00:00 2001 From: Chip Kent <5250374+chipkent@users.noreply.github.com> Date: Mon, 6 Dec 2021 13:31:11 -0700 Subject: [PATCH 1/4] Add an or filter --- Integrations/python/deephaven/filter.py | 61 +++++++++++++++++++++++++ Integrations/python/test/test_filter.py | 31 +++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 Integrations/python/deephaven/filter.py create mode 100644 Integrations/python/test/test_filter.py diff --git a/Integrations/python/deephaven/filter.py b/Integrations/python/deephaven/filter.py new file mode 100644 index 00000000000..0224e53aff2 --- /dev/null +++ b/Integrations/python/deephaven/filter.py @@ -0,0 +1,61 @@ +# +# Copyright (c) 2016-2021 Deephaven Data Labs and Patent Pending +# +""" The deephaven.filter module provides methods for filtering Deephaven tables.""" + +from typing import List + +import jpy +import wrapt + +_JFilter = None +_JFilterOr = None + + +def _defineSymbols(): + """ + Defines appropriate java symbol, which requires that the jvm has been initialized through the :class:`jpy` module, + for use throughout the module AT RUNTIME. This is versus static definition upon first import, which would lead to an + exception if the jvm wasn't initialized BEFORE importing the module. + """ + + if not jpy.has_jvm(): + raise SystemError("No java functionality can be used until the JVM has been initialized through the jpy module") + + global _JFilter, _JFilterOr + + if _JFilter is None: + # This will raise an exception if the desired object is not the classpath + _JFilter = jpy.get_type("io.deephaven.api.filter.Filter") + _JCsvSpecs = jpy.get_type("io.deephaven.api.filter.FilterOr") + + +# every module method should be decorated with @_passThrough +@wrapt.decorator +def _passThrough(wrapped, instance, args, kwargs): + """ + For decoration of module methods, to define necessary symbols at runtime + + :param wrapped: the method to be decorated + :param instance: the object to which the wrapped function was bound when it was called + :param args: the argument list for `wrapped` + :param kwargs: the keyword argument dictionary for `wrapped` + :return: the decorated version of the method + """ + + _defineSymbols() + return wrapped(*args, **kwargs) + + +@_passThrough +def or_(filters:List[str]) -> object: + """ Filters on cases where any of the input filters evaluate to true. + + Args: + filters (List[str]): a list of filters + + Returns: + a filter that evaluates to true when any of the input filters evaluates to true + """ + + return _JFilterOr.of(_JFilter.from(filters)) diff --git a/Integrations/python/test/test_filter.py b/Integrations/python/test/test_filter.py new file mode 100644 index 00000000000..b2605c0411a --- /dev/null +++ b/Integrations/python/test/test_filter.py @@ -0,0 +1,31 @@ +# +# Copyright (c) 2016-2021 Deephaven Data Labs and Patent Pending +# +import unittest + +from deephaven.TableTools import newTable, intCol +from deephaven.filter import or_ + +from deephaven import Types +from deephaven import read_csv +from unittest import TestCase + + +class FilterTestCase(TestCase): + def test_or(self): + t = newTable( + intCol("A", 1, 2, 3, 4, 5), + intCol("B", 11, 12, 13, 14, 15) + ) + + t_target = newTable( + intCol("A", 3, 4), + intCol("B", 13, 14) + ) + + t_actual = t.where(or_("A>2", "B<=14")) + self.assertEqual(t_target, t_actual) + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file From 8adf10b6bda74b272689e0b9c12143ede03b7de9 Mon Sep 17 00:00:00 2001 From: Jianfeng Mao <4297243+jmao-denver@users.noreply.github.com> Date: Mon, 6 Dec 2021 13:40:44 -0700 Subject: [PATCH 2/4] Update filter.py --- Integrations/python/deephaven/filter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Integrations/python/deephaven/filter.py b/Integrations/python/deephaven/filter.py index 0224e53aff2..431e7b49d45 100644 --- a/Integrations/python/deephaven/filter.py +++ b/Integrations/python/deephaven/filter.py @@ -58,4 +58,4 @@ def or_(filters:List[str]) -> object: a filter that evaluates to true when any of the input filters evaluates to true """ - return _JFilterOr.of(_JFilter.from(filters)) + return _JFilterOr.of(_JFilter.from_(filters)) From 578ed92d60bbefc2099fea5980b7e2d062ca2e53 Mon Sep 17 00:00:00 2001 From: Chip Kent Date: Mon, 6 Dec 2021 14:23:29 -0700 Subject: [PATCH 3/4] Fixed unit test and code after running. --- Integrations/python/deephaven/__init__.py | 4 +++- Integrations/python/deephaven/filter.py | 8 +++----- Integrations/python/test/test_filter.py | 15 +++++++-------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/Integrations/python/deephaven/__init__.py b/Integrations/python/deephaven/__init__.py index b6987f81b3e..15d691abe17 100644 --- a/Integrations/python/deephaven/__init__.py +++ b/Integrations/python/deephaven/__init__.py @@ -90,7 +90,8 @@ ParquetTools as pt, \ TableTools as ttools, \ TableLoggers as tloggers, \ - Types as dh + Types as dh, \ + filter as _filter from .Plot import figure_wrapper as figw @@ -119,6 +120,7 @@ def initialize(): ttools._defineSymbols() tloggers._defineSymbols() csv._defineSymbols() + _filter._defineSymbols() import deephaven.TableManipulation deephaven.TableManipulation._defineSymbols() diff --git a/Integrations/python/deephaven/filter.py b/Integrations/python/deephaven/filter.py index 431e7b49d45..be0543cd3e3 100644 --- a/Integrations/python/deephaven/filter.py +++ b/Integrations/python/deephaven/filter.py @@ -3,8 +3,6 @@ # """ The deephaven.filter module provides methods for filtering Deephaven tables.""" -from typing import List - import jpy import wrapt @@ -27,7 +25,7 @@ def _defineSymbols(): if _JFilter is None: # This will raise an exception if the desired object is not the classpath _JFilter = jpy.get_type("io.deephaven.api.filter.Filter") - _JCsvSpecs = jpy.get_type("io.deephaven.api.filter.FilterOr") + _JFilterOr = jpy.get_type("io.deephaven.api.filter.FilterOr") # every module method should be decorated with @_passThrough @@ -48,11 +46,11 @@ def _passThrough(wrapped, instance, args, kwargs): @_passThrough -def or_(filters:List[str]) -> object: +def or_(*filters) -> object: """ Filters on cases where any of the input filters evaluate to true. Args: - filters (List[str]): a list of filters + filters (*str): a list of filters Returns: a filter that evaluates to true when any of the input filters evaluates to true diff --git a/Integrations/python/test/test_filter.py b/Integrations/python/test/test_filter.py index b2605c0411a..f39961a79fe 100644 --- a/Integrations/python/test/test_filter.py +++ b/Integrations/python/test/test_filter.py @@ -3,11 +3,8 @@ # import unittest -from deephaven.TableTools import newTable, intCol +from deephaven.TableTools import newTable, intCol, diff from deephaven.filter import or_ - -from deephaven import Types -from deephaven import read_csv from unittest import TestCase @@ -19,12 +16,14 @@ def test_or(self): ) t_target = newTable( - intCol("A", 3, 4), - intCol("B", 13, 14) + intCol("A", 1, 4, 5), + intCol("B", 11, 14, 15) ) - t_actual = t.where(or_("A>2", "B<=14")) - self.assertEqual(t_target, t_actual) + t_actual = t.where(or_("A<2", "B>=14")) + + diff_string = diff(t_actual, t_target, 0) + self.assertEqual(0, len(diff_string)) if __name__ == '__main__': From 219787a22d8f7e7192de3a8c30bfb33f1019beb8 Mon Sep 17 00:00:00 2001 From: Chip Kent Date: Mon, 6 Dec 2021 15:12:38 -0700 Subject: [PATCH 4/4] Addressed code review. --- Integrations/python/deephaven/filter.py | 2 +- Integrations/python/test/test_filter.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Integrations/python/deephaven/filter.py b/Integrations/python/deephaven/filter.py index be0543cd3e3..772f1fe0f45 100644 --- a/Integrations/python/deephaven/filter.py +++ b/Integrations/python/deephaven/filter.py @@ -50,7 +50,7 @@ def or_(*filters) -> object: """ Filters on cases where any of the input filters evaluate to true. Args: - filters (*str): a list of filters + *filters (str): the filter expressions Returns: a filter that evaluates to true when any of the input filters evaluates to true diff --git a/Integrations/python/test/test_filter.py b/Integrations/python/test/test_filter.py index f39961a79fe..9e7fa56df5d 100644 --- a/Integrations/python/test/test_filter.py +++ b/Integrations/python/test/test_filter.py @@ -22,8 +22,8 @@ def test_or(self): t_actual = t.where(or_("A<2", "B>=14")) - diff_string = diff(t_actual, t_target, 0) - self.assertEqual(0, len(diff_string)) + diff_string = diff(t_actual, t_target, 1) + self.assertEqual("", diff_string) if __name__ == '__main__':