diff --git a/py/server/deephaven/filters.py b/py/server/deephaven/filters.py index a7612abc551..719a4fc679b 100644 --- a/py/server/deephaven/filters.py +++ b/py/server/deephaven/filters.py @@ -37,6 +37,14 @@ def j_object(self) -> jpy.JType: def __init__(self, j_filter): self.j_filter = j_filter + def not_(self): + """Creates a new filter that evaluates to the opposite of what this filter evaluates to. + + Returns: + a new not Filter + """ + return Filter(j_filter=_JFilterNot.of(self.j_filter)) + @classmethod def from_(cls, conditions: Union[str, List[str]]) -> Union[Filter, List[Filter]]: """Creates filter(s) from the given condition(s). @@ -68,7 +76,7 @@ def or_(filters: List[Filter]) -> Filter: filters (List[filter]): the component filters Returns: - a new Filter + a new or Filter """ return Filter(j_filter=_JFilterOr.of(*[f.j_filter for f in filters])) @@ -80,21 +88,45 @@ def and_(filters: List[Filter]) -> Filter: filters (List[filter]): the component filters Returns: - a new Filter + a new and Filter """ return Filter(j_filter=_JFilterAnd.of(*[f.j_filter for f in filters])) def not_(filter_: Filter) -> Filter: - """Creates a new filter that evaluates to true when the given filter evaluates to false. + """Creates a new filter that evaluates to the opposite of what filter_ evaluates to. Args: filter_ (Filter): the filter to negate with Returns: - a new Filter + a new not Filter + """ + return filter_.not_() + + +def is_null(col: str) -> Filter: + """Creates a new filter that evaluates to true when the col is null, and evaluates to false when col is not null. + + Args: + col (str): the column name + + Returns: + a new is-null Filter + """ + return Filter(j_filter=_JFilter.isNull(_JColumnName.of(col))) + + +def is_not_null(col: str) -> Filter: + """Creates a new filter that evaluates to true when the col is not null, and evaluates to false when col is null. + + Args: + col (str): the column name + + Returns: + a new is-not-null Filter """ - return Filter(j_filter=_JFilterNot.of(filter_.j_filter)) + return Filter(j_filter=_JFilter.isNotNull(_JColumnName.of(col))) class PatternMode(Enum): diff --git a/py/server/tests/test_filters.py b/py/server/tests/test_filters.py index 8020ba5836e..ef2829d911d 100644 --- a/py/server/tests/test_filters.py +++ b/py/server/tests/test_filters.py @@ -4,8 +4,9 @@ import unittest -from deephaven import read_csv, DHError -from deephaven.filters import Filter, PatternMode, and_, or_, not_, pattern +from deephaven import new_table, read_csv, DHError +from deephaven.column import string_col +from deephaven.filters import Filter, PatternMode, and_, is_not_null, is_null, or_, not_, pattern from tests.testbase import BaseTestCase @@ -51,6 +52,19 @@ def test_filter(self): filtered_table_not = self.test_table.where(filter_not) self.assertEqual(filtered_table_or.size + filtered_table_not.size, self.test_table.size) + def test_is_null(self): + x = new_table([string_col("X", ["a", "b", "c", None, "e", "f"])]) + x_is_null = new_table([string_col("X", [None])]) + x_not_is_null = new_table([string_col("X", ["a", "b", "c", "e", "f"])]) + self.assert_table_equals(x.where(is_null("X")), x_is_null) + self.assert_table_equals(x.where(not_(is_null("X"))), x_not_is_null) + + def test_is_not_null(self): + x = new_table([string_col("X", ["a", "b", "c", None, "e", "f"])]) + x_is_not_null = new_table([string_col("X", ["a", "b", "c", "e", "f"])]) + x_not_is_not_null = new_table([string_col("X", [None])]) + self.assert_table_equals(x.where(is_not_null("X")), x_is_not_null) + self.assert_table_equals(x.where(not_(is_not_null("X"))), x_not_is_not_null) if __name__ == '__main__': unittest.main()