@@ -218,6 +218,15 @@ def test_server(connect_server):
218218 raise RSConnectException ("\n " .join (failures ))
219219
220220
221+ def test_shinyapps_server (server : api .ShinyappsServer ):
222+ with api .ShinyappsClient (server ) as client :
223+ try :
224+ result = client .get_current_user ()
225+ server .handle_bad_response (result )
226+ except RSConnectException as exc :
227+ raise RSConnectException ("Failed to verify with shinyapps.io ({})." .format (exc ))
228+
229+
221230def test_api_key (connect_server ):
222231 """
223232 Test that an API Key may be used to authenticate with the given RStudio Connect server.
@@ -313,7 +322,7 @@ def check_server_capabilities(connect_server, capability_functions, details_sour
313322 raise RSConnectException (message )
314323
315324
316- def _make_deployment_name (connect_server , title , force_unique ) -> str :
325+ def _make_deployment_name (remote_server : api . TargetableServer , title : str , force_unique : bool ) -> str :
317326 """
318327 Produce a name for a deployment based on its title. It is assumed that the
319328 title is already defaulted and validated as appropriate (meaning the title
@@ -324,7 +333,7 @@ def _make_deployment_name(connect_server, title, force_unique) -> str:
324333 that we collapse repeating underscores and, if the name is too short, it is
325334 padded to the left with underscores.
326335
327- :param connect_server : the information needed to interact with the Connect server.
336+ :param remote_server : the information needed to interact with the Connect server.
328337 :param title: the title to start with.
329338 :param force_unique: a flag noting whether the generated name must be forced to be
330339 unique.
@@ -338,7 +347,7 @@ def _make_deployment_name(connect_server, title, force_unique) -> str:
338347
339348 # Now, make sure it's unique, if needed.
340349 if force_unique :
341- name = api .find_unique_name (connect_server , name )
350+ name = api .find_unique_name (remote_server , name )
342351
343352 return name
344353
@@ -903,6 +912,62 @@ def deploy_python_fastapi(
903912 )
904913
905914
915+ def deploy_python_shiny (
916+ connect_server ,
917+ directory ,
918+ extra_files ,
919+ excludes ,
920+ entry_point ,
921+ new = False ,
922+ app_id = None ,
923+ title = None ,
924+ python = None ,
925+ conda_mode = False ,
926+ force_generate = False ,
927+ log_callback = None ,
928+ ):
929+ """
930+ A function to deploy a Python Shiny module to RStudio Connect. Depending on the files involved
931+ and network latency, this may take a bit of time.
932+
933+ :param connect_server: the Connect server information.
934+ :param directory: the app directory to deploy.
935+ :param extra_files: any extra files that should be included in the deploy.
936+ :param excludes: a sequence of glob patterns that will exclude matched files.
937+ :param entry_point: the module/executable object for the WSGi framework.
938+ :param new: a flag to force this as a new deploy.
939+ :param app_id: the ID of an existing application to deploy new files for.
940+ :param title: an optional title for the deploy. If this is not provided, ne will
941+ be generated.
942+ :param python: the optional name of a Python executable.
943+ :param conda_mode: use conda to build an environment.yml
944+ instead of conda, when conda is not supported on RStudio Connect (version<=1.8.0).
945+ :param force_generate: force generating "requirements.txt" or "environment.yml",
946+ even if it already exists.
947+ :param log_callback: the callback to use to write the log to. If this is None
948+ (the default) the lines from the deployment log will be returned as a sequence.
949+ If a log callback is provided, then None will be returned for the log lines part
950+ of the return tuple.
951+ :return: the ultimate URL where the deployed app may be accessed and the sequence
952+ of log lines. The log lines value will be None if a log callback was provided.
953+ """
954+ return _deploy_by_python_framework (
955+ connect_server ,
956+ directory ,
957+ extra_files ,
958+ excludes ,
959+ entry_point ,
960+ gather_basic_deployment_info_for_shiny ,
961+ new ,
962+ app_id ,
963+ title ,
964+ python ,
965+ conda_mode ,
966+ force_generate ,
967+ log_callback ,
968+ )
969+
970+
906971def deploy_dash_app (
907972 connect_server : api .RSConnectServer ,
908973 directory : str ,
@@ -1447,7 +1512,7 @@ def _generate_gather_basic_deployment_info_for_python(app_mode: AppMode) -> typi
14471512 """
14481513
14491514 def gatherer (
1450- connect_server : api .RSConnectServer ,
1515+ remote_server : api .TargetableServer ,
14511516 app_store : AppStore ,
14521517 directory : str ,
14531518 entry_point : str ,
@@ -1456,7 +1521,7 @@ def gatherer(
14561521 title : str ,
14571522 ) -> typing .Tuple [str , int , str , str , bool , AppMode ]:
14581523 return _gather_basic_deployment_info_for_framework (
1459- connect_server ,
1524+ remote_server ,
14601525 app_store ,
14611526 directory ,
14621527 entry_point ,
@@ -1474,10 +1539,11 @@ def gatherer(
14741539gather_basic_deployment_info_for_dash = _generate_gather_basic_deployment_info_for_python (AppModes .DASH_APP )
14751540gather_basic_deployment_info_for_streamlit = _generate_gather_basic_deployment_info_for_python (AppModes .STREAMLIT_APP )
14761541gather_basic_deployment_info_for_bokeh = _generate_gather_basic_deployment_info_for_python (AppModes .BOKEH_APP )
1542+ gather_basic_deployment_info_for_shiny = _generate_gather_basic_deployment_info_for_python (AppModes .PYTHON_SHINY )
14771543
14781544
14791545def _gather_basic_deployment_info_for_framework (
1480- connect_server : api .RSConnectServer ,
1546+ remote_server : api .TargetableServer ,
14811547 app_store : AppStore ,
14821548 directory : str ,
14831549 entry_point : str ,
@@ -1489,7 +1555,7 @@ def _gather_basic_deployment_info_for_framework(
14891555 """
14901556 Helps to gather the necessary info for performing a deployment.
14911557
1492- :param connect_server : the Connect server information.
1558+ :param remote_server : the server information.
14931559 :param app_store: the store for the specified directory.
14941560 :param directory: the primary file being deployed.
14951561 :param entry_point: the entry point for the API in '<module>:<object> format. if
@@ -1514,13 +1580,19 @@ def _gather_basic_deployment_info_for_framework(
15141580 if app_id is None :
15151581 # Possible redeployment - check for saved metadata.
15161582 # Use the saved app information unless overridden by the user.
1517- app_id , existing_app_mode = app_store .resolve (connect_server .url , app_id , app_mode )
1583+ app_id , existing_app_mode = app_store .resolve (remote_server .url , app_id , app_mode )
15181584 logger .debug ("Using app mode from app %s: %s" % (app_id , app_mode ))
15191585 elif app_id is not None :
15201586 # Don't read app metadata if app-id is specified. Instead, we need
15211587 # to get this from Connect.
1522- app = api .get_app_info (connect_server , app_id )
1523- existing_app_mode = AppModes .get_by_ordinal (app .get ("app_mode" , 0 ), True )
1588+ if isinstance (remote_server , api .RSConnectServer ):
1589+ app = api .get_app_info (remote_server , app_id )
1590+ existing_app_mode = AppModes .get_by_ordinal (app .get ("app_mode" , 0 ), True )
1591+ elif isinstance (remote_server , api .ShinyappsServer ):
1592+ app = api .get_shinyapp_info (remote_server , app_id )
1593+ existing_app_mode = AppModes .get_by_cloud_name (app .json_data ["mode" ])
1594+ else :
1595+ raise RSConnectException ("Unable to infer Connect client." )
15241596 if existing_app_mode and app_mode != existing_app_mode :
15251597 msg = (
15261598 "Deploying with mode '%s',\n "
@@ -1538,7 +1610,7 @@ def _gather_basic_deployment_info_for_framework(
15381610 return (
15391611 entry_point ,
15401612 app_id ,
1541- _make_deployment_name (connect_server , title , app_id is None ),
1613+ _make_deployment_name (remote_server , title , app_id is None ),
15421614 title ,
15431615 default_title ,
15441616 app_mode ,
@@ -1697,7 +1769,7 @@ def create_quarto_deployment_bundle(
16971769
16981770
16991771def deploy_bundle (
1700- connect_server : api .RSConnectServer ,
1772+ remote_server : api .TargetableServer ,
17011773 app_id : int ,
17021774 name : str ,
17031775 title : str ,
@@ -1708,7 +1780,7 @@ def deploy_bundle(
17081780 """
17091781 Deploys the specified bundle.
17101782
1711- :param connect_server : the Connect server information.
1783+ :param remote_server : the server information.
17121784 :param app_id: the ID of the app to deploy, if this is a redeploy.
17131785 :param name: the name for the deploy.
17141786 :param title: the title for the deploy.
@@ -1718,7 +1790,17 @@ def deploy_bundle(
17181790 :return: application information about the deploy. This includes the ID of the
17191791 task that may be queried for deployment progress.
17201792 """
1721- return api .do_bundle_deploy (connect_server , app_id , name , title , title_is_default , bundle , env_vars )
1793+ ce = RSConnectExecutor (
1794+ server = remote_server ,
1795+ app_id = app_id ,
1796+ name = name ,
1797+ title = title ,
1798+ title_is_default = title_is_default ,
1799+ bundle = bundle ,
1800+ env_vars = env_vars ,
1801+ )
1802+ ce .deploy_bundle ()
1803+ return ce .state ["deployed_info" ]
17221804
17231805
17241806def spool_deployment_log (connect_server , app , log_callback ):
0 commit comments