diff --git a/py/server/deephaven/jcompat.py b/py/server/deephaven/jcompat.py index a4fb34c2495..46cb3d79a3a 100644 --- a/py/server/deephaven/jcompat.py +++ b/py/server/deephaven/jcompat.py @@ -12,7 +12,7 @@ import pandas as pd from deephaven import dtypes, DHError -from deephaven._wrapper import unwrap, wrap_j_object +from deephaven._wrapper import unwrap, wrap_j_object, JObjectWrapper from deephaven.dtypes import DType, _PRIMITIVE_DTYPE_NULL_MAP, _J_ARRAY_NP_TYPE_MAP _NULL_BOOLEAN_AS_BYTE = jpy.get_type("io.deephaven.util.BooleanUtils").NULL_BOOLEAN_AS_BYTE @@ -304,3 +304,33 @@ def _j_array_to_series(dtype: DType, j_array: jpy.JType, conv_null: bool) -> pd. s = pd.Series(data=np_array, copy=False) return s + + +class AutoCloseable(JObjectWrapper): + """A context manager wrapper to allow Java AutoCloseable to be used in with statements. + + When constructing a new instance, the Java AutoCloseable must not be closed.""" + + j_object_type = jpy.get_type("java.lang.AutoCloseable") + + def __init__(self, j_auto_closeable): + self._j_auto_closeable = j_auto_closeable + self.closed = False + + def __enter__(self): + return self + + def close(self): + if not self.closed: + self.closed = True + self._j_auto_closeable.close() + + def __exit__(self, exc_type, exc_value, traceback): + self.close() + + def __del__(self): + self.close() + + @property + def j_object(self) -> jpy.JType: + return self._j_auto_closeable diff --git a/py/server/tests/test_jcompat.py b/py/server/tests/test_jcompat.py index bcea58d112c..40241b73da2 100644 --- a/py/server/tests/test_jcompat.py +++ b/py/server/tests/test_jcompat.py @@ -5,11 +5,12 @@ import unittest from deephaven import dtypes -from deephaven.jcompat import j_function, j_lambda +from deephaven.jcompat import j_function, j_lambda, AutoCloseable from tests.testbase import BaseTestCase import jpy +_JSharedContext = jpy.get_type("io.deephaven.engine.table.SharedContext") class JCompatTestCase(BaseTestCase): def test_j_function(self): @@ -29,6 +30,12 @@ def int_to_str(v: int) -> str: r = j_func.apply(10) self.assertEqual(r, "10") + def test_auto_closeable(self): + auto_closeable = AutoCloseable(_JSharedContext.makeSharedContext()) + with auto_closeable: + self.assertEqual(auto_closeable.closed, False) + self.assertEqual(auto_closeable.closed, True) + if __name__ == "__main__": unittest.main()