Skip to content

Commit 15e9ced

Browse files
Niall Egansusodapop
authored andcommitted
Iterator + context managerAPI
This small PR adds APIs to the Python client for iteration and context managers. New unit tests Author: Niall Egan <niall.egan@databricks.com>
1 parent b3f6fb0 commit 15e9ced

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

cmdexec/clients/python/command_exec_client.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ def __init__(self, **kwargs):
4242
logger.info("Successfully opened session " + str(self.session_id.hex()))
4343
self._cursors = []
4444

45+
def __enter__(self):
46+
return self
47+
48+
def __exit__(self, exc_type, exc_value, traceback):
49+
self.close()
50+
4551
def cursor(self, buffer_size_rows=DEFAULT_BUFFER_SIZE_ROWS):
4652
if not self.open:
4753
raise Error("Cannot create cursor from closed connection")
@@ -69,6 +75,19 @@ def __init__(self, connection, buffer_size_rows=DEFAULT_BUFFER_SIZE_ROWS):
6975
# Note that Cursor closed => active result set closed, but not vice versa
7076
self.open = True
7177

78+
def __enter__(self):
79+
return self
80+
81+
def __exit__(self, exc_type, exc_value, traceback):
82+
self.close()
83+
84+
def __iter__(self):
85+
if self.active_result_set:
86+
for row in self.active_result_set:
87+
yield row
88+
else:
89+
raise Error("There is no active result set")
90+
7291
def _response_to_result_set(self, execute_command_response, status):
7392
command_id = execute_command_response.command_id
7493
arrow_results = execute_command_response.results.arrow_ipc_stream
@@ -199,6 +218,14 @@ def __init__(self,
199218
# In this case, there are results waiting on the server so we fetch now for simplicity
200219
self._fill_results_buffer()
201220

221+
def __iter__(self):
222+
while True:
223+
row = self.fetchone()
224+
if row:
225+
yield row
226+
else:
227+
break
228+
202229
def _fetch_and_deserialize_results(self):
203230
fetch_results_request = command_pb2.FetchCommandResultsRequest(
204231
id=self.command_id,

cmdexec/clients/python/tests/tests.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,25 @@ def test_negative_fetch_throws_exception(self, pyarrow_ipc_open_stream_mock):
176176
with self.assertRaises(ValueError) as e:
177177
result_set.fetchmany(-1)
178178

179+
def test_context_manager_closes_cursor(self):
180+
mock_close = Mock()
181+
with command_exec_client.Cursor(Mock()) as cursor:
182+
cursor.close = mock_close
183+
mock_close.assert_called_once_with()
184+
185+
@patch("cmdexec.clients.python.command_exec_client.CmdExecBaseHttpClient")
186+
def test_context_manager_closes_connection(self, mock_client_class):
187+
instance = mock_client_class.return_value
188+
mock_response = Mock()
189+
mock_response.id = b'\x22'
190+
instance.make_request.return_value = mock_response
191+
good_connection_args = {"HOST": 1, "PORT": 1}
192+
mock_close = Mock()
193+
194+
with command_exec_client.connect(**good_connection_args) as connection:
195+
connection.close = mock_close
196+
mock_close.assert_called_once_with()
197+
179198

180199
if __name__ == '__main__':
181200
suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])

0 commit comments

Comments
 (0)