Skip to content

Commit 800b984

Browse files
committed
feat: remote R session management added
1 parent fa26592 commit 800b984

File tree

2 files changed

+157
-4
lines changed

2 files changed

+157
-4
lines changed

datashield/api.py

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,27 +127,35 @@ def close(self, save: str = None) -> None:
127127
def has_connections(self) -> bool:
128128
"""
129129
Check if some connections were opened.
130+
131+
:return: True if some connections were opened, False otherwise
130132
"""
131133
return len(self.conns) > 0
132134

133135
def get_connection_names(self) -> list[str]:
134136
"""
135137
Get the opened connection names.
138+
139+
:return: The list of opened connection names
136140
"""
137141
if self.conns:
138142
return [conn.name for conn in self.conns]
139143
else:
140-
return None
144+
return []
141145

142146
def has_errors(self) -> bool:
143147
"""
144148
Check if last command execution has produced errors.
149+
150+
:return: True if last command execution has produced errors, False otherwise
145151
"""
146152
return len(self.errors) > 0
147153

148154
def get_errors(self) -> dict:
149155
"""
150156
Get the last command execution errors, per remote server name.
157+
158+
:return: The last command execution errors, per remote server name
151159
"""
152160
return self.errors
153161

@@ -158,6 +166,8 @@ def get_errors(self) -> dict:
158166
def tables(self) -> dict:
159167
"""
160168
List available table names from the data repository.
169+
170+
:return: The available table names from the data repository, per remote server name
161171
"""
162172
rval = {}
163173
for conn in self.conns:
@@ -167,6 +177,8 @@ def tables(self) -> dict:
167177
def resources(self) -> dict:
168178
"""
169179
List available resource names from the data repository.
180+
181+
:return: The available resource names from the data repository, per remote server name
170182
"""
171183
rval = {}
172184
for conn in self.conns:
@@ -176,6 +188,8 @@ def resources(self) -> dict:
176188
def profiles(self) -> dict:
177189
"""
178190
List available DataSHIELD profile names in the data repository.
191+
192+
:return: The available DataSHIELD profile names in the data repository, per remote server name
179193
"""
180194
rval = {}
181195
for conn in self.conns:
@@ -185,6 +199,8 @@ def profiles(self) -> dict:
185199
def packages(self) -> dict:
186200
"""
187201
Get the list of DataSHIELD packages with their version, that have been configured on the remote data repository.
202+
203+
:return: The list of DataSHIELD packages with their version, that have been configured on the remote data repository, per remote server name
188204
"""
189205
rval = {}
190206
for conn in self.conns:
@@ -196,6 +212,7 @@ def methods(self, type: str = "aggregate") -> dict:
196212
Get the list of DataSHIELD methods that have been configured on the remote data repository.
197213
198214
:param type: The type of method, either "aggregate" (default) or "assign"
215+
:return: The list of DataSHIELD methods that have been configured on the remote data repository, per remote server name
199216
"""
200217
rval = {}
201218
for conn in self.conns:
@@ -209,6 +226,8 @@ def methods(self, type: str = "aggregate") -> dict:
209226
def workspaces(self) -> dict:
210227
"""
211228
Get the list of DataSHIELD workspaces, that have been saved on the remote data repository.
229+
230+
:return: The list of DataSHIELD workspaces, that have been saved on the remote data repository, per remote server name
212231
"""
213232
rval = {}
214233
for conn in self.conns:
@@ -220,39 +239,66 @@ def workspace_save(self, name: str) -> dict:
220239
Save the DataSHIELD R session in a workspace on the remote data repository.
221240
222241
:param name: The name of the workspace
242+
:return: The list of DataSHIELD workspaces, that have been saved on the remote data repository after saving the workspace, per remote server name
223243
"""
224244
for conn in self.conns:
225245
conn.save_workspace(f"{conn.name}:{name}")
246+
return self.workspaces()
226247

227248
def workspace_restore(self, name: str) -> dict:
228249
"""
229250
Restore a saved DataSHIELD R session from the remote data repository. When restoring a workspace,
230251
any existing symbol or file with same name will be overridden.
231252
232253
:param name: The name of the workspace
254+
:return: The list of DataSHIELD workspaces, that have been saved on the remote data repository after restoring the workspace, per remote server name
233255
"""
234256
for conn in self.conns:
235257
conn.restore_workspace(f"{conn.name}:{name}")
258+
return self.workspaces()
236259

237260
def workspace_rm(self, name: str) -> dict:
238261
"""
239262
Remove a DataSHIELD workspace from the remote data repository. Ignored if no
240263
such workspace exists.
241264
242265
:param name: The name of the workspace
266+
:return: The list of DataSHIELD workspaces, that have been saved on the remote data repository after removing the workspace, per remote server name
243267
"""
244268
for conn in self.conns:
245269
conn.rm_workspace(f"{conn.name}:{name}")
270+
return self.workspaces()
246271

247272
#
248273
# R session
249274
#
250275

276+
def sessions(self) -> dict:
277+
"""
278+
Ensure R sessions are started on the remote servers and get their information.
279+
280+
:return: The R session information, per remote server name
281+
"""
282+
rval = {}
283+
for conn in self.conns:
284+
if not conn.has_session():
285+
conn.start_session(asynchronous=True)
286+
# check for session status and wait until all are complete
287+
while any(conn.get_session().is_pending() for conn in self.conns):
288+
time.sleep(0.1)
289+
for conn in self.conns:
290+
rval[conn.name] = conn.get_session()
291+
self._check_errors()
292+
return rval
293+
251294
def ls(self) -> dict:
252295
"""
253296
After assignments have been performed, list the symbols that live in the DataSHIELD R session on the server side.
297+
298+
:return: The symbols that live in the DataSHIELD R session on the server side, per remote server name
254299
"""
255300
self._init_errors()
301+
self.sessions() # ensure sessions are started and available
256302
rval = {}
257303
for conn in self.conns:
258304
try:
@@ -263,11 +309,14 @@ def ls(self) -> dict:
263309
self._check_errors()
264310
return rval
265311

266-
def rm(self, symbol: str):
312+
def rm(self, symbol: str) -> None:
267313
"""
268314
Remove a symbol from remote servers.
315+
316+
:param symbol: The name of the symbol to remove
269317
"""
270318
self._init_errors()
319+
self.sessions() # ensure sessions are started and available
271320
for conn in self.conns:
272321
try:
273322
conn.rm_symbol(symbol)
@@ -295,6 +344,7 @@ def assign_table(
295344
:param asynchronous: Whether the operation is asynchronous (if supported by the DataSHIELD server)
296345
"""
297346
self._init_errors()
347+
self.sessions() # ensure sessions are started and available
298348
cmd = {}
299349
for conn in self.conns:
300350
name = table
@@ -321,6 +371,7 @@ def assign_resource(
321371
:param asynchronous: Whether the operation is asynchronous (if supported by the DataSHIELD server)
322372
"""
323373
self._init_errors()
374+
self.sessions() # ensure sessions are started and available
324375
cmd = {}
325376
for conn in self.conns:
326377
name = resource
@@ -344,6 +395,7 @@ def assign_expr(self, symbol: str, expr: str, asynchronous: bool = True) -> None
344395
:param asynchronous: Whether the operation is asynchronous (if supported by the DataSHIELD server)
345396
"""
346397
self._init_errors()
398+
self.sessions() # ensure sessions are started and available
347399
cmd = {}
348400
for conn in self.conns:
349401
try:
@@ -361,8 +413,10 @@ def aggregate(self, expr: str, asynchronous: bool = True) -> dict:
361413
362414
:param expr: The R expression to evaluate and which result will be returned
363415
:param asynchronous: Whether the operation is asynchronous (if supported by the DataSHIELD server)
416+
:return: The result of the aggregation expression evaluation, per remote server name
364417
"""
365418
self._init_errors()
419+
self.sessions() # ensure sessions are started and available
366420
cmd = {}
367421
rval = {}
368422
for conn in self.conns:

0 commit comments

Comments
 (0)