1
1
import copy
2
+ import inspect
2
3
from re import compile
3
4
import time
4
5
import requests
@@ -49,7 +50,9 @@ def _check_endpoint_name(name):
49
50
50
51
51
52
class Client :
52
- def __init__ (self , endpoint , query_timeout = 1000 ):
53
+ def __init__ (
54
+ self , endpoint , query_timeout = 1000 , remote_server = False , localhost_endpoint = None
55
+ ):
53
56
"""
54
57
Connects to a running server.
55
58
@@ -63,10 +66,19 @@ def __init__(self, endpoint, query_timeout=1000):
63
66
64
67
query_timeout : float, optional
65
68
The timeout for query operations.
69
+
70
+ remote_server : bool, optional
71
+ Whether client is a remote TabPy server.
72
+
73
+ localhost_endpoint : str, optional
74
+ The localhost endpoint with potentially different protocol and
75
+ port compared to the main endpoint parameter.
66
76
"""
67
77
_check_hostname (endpoint )
68
78
69
79
self ._endpoint = endpoint
80
+ self ._remote_server = remote_server
81
+ self ._localhost_endpoint = localhost_endpoint
70
82
71
83
session = requests .session ()
72
84
session .verify = False
@@ -232,6 +244,12 @@ def deploy(self, name, obj, description="", schema=None, override=False, is_publ
232
244
--------
233
245
remove, get_endpoints
234
246
"""
247
+ if self ._remote_server :
248
+ return self ._remote_deploy (
249
+ name , obj ,
250
+ description = description , schema = schema , override = override , is_public = is_public
251
+ )
252
+
235
253
endpoint = self .get_endpoints ().get (name )
236
254
version = 1
237
255
if endpoint :
@@ -390,6 +408,7 @@ def _gen_endpoint(self, name, obj, description, version=1, schema=None, is_publi
390
408
"methods" : endpoint_object .get_methods (),
391
409
"required_files" : [],
392
410
"required_packages" : [],
411
+ "docstring" : endpoint_object .get_docstring (),
393
412
"schema" : copy .copy (schema ),
394
413
"is_public" : is_public ,
395
414
}
@@ -419,6 +438,7 @@ def _wait_for_endpoint_deployment(
419
438
logger .info (
420
439
f"Waiting for endpoint { endpoint_name } to deploy to " f"version { version } "
421
440
)
441
+ time .sleep (interval )
422
442
start = time .time ()
423
443
while True :
424
444
ep_status = self .get_status ()
@@ -447,6 +467,72 @@ def _wait_for_endpoint_deployment(
447
467
logger .info (f"Sleeping { interval } ..." )
448
468
time .sleep (interval )
449
469
470
+ def _remote_deploy (
471
+ self , name , obj , description = "" , schema = None , override = False , is_public = False
472
+ ):
473
+ """
474
+ Remotely deploy a Python function using the /evaluate endpoint. Takes the same inputs
475
+ as deploy.
476
+ """
477
+ remote_script = self ._gen_remote_script ()
478
+ remote_script += f"{ inspect .getsource (obj )} \n "
479
+
480
+ remote_script += (
481
+ f"client.deploy("
482
+ f"'{ name } ', { obj .__name__ } , '{ description } ', "
483
+ f"override={ override } , is_public={ is_public } , schema={ schema } "
484
+ f")"
485
+ )
486
+
487
+ return self ._evaluate_remote_script (remote_script )
488
+
489
+ def _gen_remote_script (self ):
490
+ """
491
+ Generates a remote script for TabPy client connection with credential handling.
492
+
493
+ Returns:
494
+ str: A Python script to establish a TabPy client connection
495
+ """
496
+ remote_script = [
497
+ "from tabpy.tabpy_tools.client import Client" ,
498
+ f"client = Client('{ self ._localhost_endpoint or self ._endpoint } ')"
499
+ ]
500
+
501
+ remote_script .append (
502
+ f"client.set_credentials('{ auth .username } ', '{ auth .password } ')"
503
+ ) if (auth := self ._service .service_client .network_wrapper .auth ) else None
504
+
505
+ return "\n " .join (remote_script ) + "\n "
506
+
507
+ def _evaluate_remote_script (self , remote_script ):
508
+ """
509
+ Uses TabPy /evaluate endpoint to execute a remote TabPy client script.
510
+
511
+ Parameters
512
+ ----------
513
+ remote_script : str
514
+ The script to execute remotely.
515
+ """
516
+ print (f"Remote script:\n { remote_script } \n " )
517
+ url = f"{ self ._endpoint } evaluate"
518
+ headers = {"Content-Type" : "application/json" }
519
+ payload = {"data" : {}, "script" : remote_script }
520
+
521
+ response = requests .post (
522
+ url ,
523
+ headers = headers ,
524
+ auth = self ._service .service_client .network_wrapper .auth ,
525
+ json = payload
526
+ )
527
+
528
+ msg = response .text .replace ('null' , 'Success' )
529
+ if "Ad-hoc scripts have been disabled" in msg :
530
+ msg += "\n [Deployment to remote tabpy client not allowed.]"
531
+
532
+ status_message = (f"{ response .status_code } - { msg } \n " )
533
+ print (status_message )
534
+ return status_message
535
+
450
536
def set_credentials (self , username , password ):
451
537
"""
452
538
Set credentials for all the TabPy client-server communication
0 commit comments