@@ -504,10 +504,19 @@ def deploy_jupyter_notebook(
504504 of log lines. The log lines value will be None if a log callback was provided.
505505 """
506506 app_store = AppStore (file_name )
507- (app_id , deployment_name , deployment_title , default_title , app_mode ,) = gather_basic_deployment_info_for_notebook (
508- connect_server , app_store , file_name , new , app_id , title , static
507+ (
508+ app_id ,
509+ deployment_name ,
510+ deployment_title ,
511+ default_title ,
512+ app_mode ,
513+ ) = gather_basic_deployment_info_for_notebook (connect_server , app_store , file_name , new , app_id , title , static )
514+ python , environment = get_python_env_info (
515+ file_name ,
516+ python ,
517+ conda_mode = conda_mode ,
518+ force_generate = force_generate ,
509519 )
510- python , environment = get_python_env_info (file_name , python , conda_mode = conda_mode , force_generate = force_generate ,)
511520 bundle = create_notebook_deployment_bundle (
512521 file_name , extra_files , app_mode , python , environment , hide_all_input , hide_tagged_input
513522 )
@@ -526,7 +535,16 @@ def deploy_jupyter_notebook(
526535
527536
528537def _finalize_deploy (
529- connect_server , app_store , file_name , app_id , app_mode , name , title , title_is_default , bundle , log_callback ,
538+ connect_server ,
539+ app_store ,
540+ file_name ,
541+ app_id ,
542+ app_mode ,
543+ name ,
544+ title ,
545+ title_is_default ,
546+ bundle ,
547+ log_callback ,
530548):
531549 """
532550 A common function to finish up the deploy process once all the data (bundle
@@ -551,7 +569,13 @@ def _finalize_deploy(
551569 app = deploy_bundle (connect_server , app_id , name , title , title_is_default , bundle )
552570 app_url , log_lines = spool_deployment_log (connect_server , app , log_callback )
553571 app_store .set (
554- connect_server .url , abspath (file_name ), app_url , app ["app_id" ], app ["app_guid" ], title , app_mode ,
572+ connect_server .url ,
573+ abspath (file_name ),
574+ app_url ,
575+ app ["app_id" ],
576+ app ["app_guid" ],
577+ title ,
578+ app_mode ,
555579 )
556580 return app_url , log_lines
557581
@@ -625,6 +649,62 @@ def deploy_python_api(
625649 )
626650
627651
652+ def deploy_python_fastapi (
653+ connect_server ,
654+ directory ,
655+ extra_files ,
656+ excludes ,
657+ entry_point ,
658+ new = False ,
659+ app_id = None ,
660+ title = None ,
661+ python = None ,
662+ conda_mode = False ,
663+ force_generate = False ,
664+ log_callback = None ,
665+ ):
666+ """
667+ A function to deploy a Python ASGI API module to RStudio Connect. Depending on the files involved
668+ and network latency, this may take a bit of time.
669+
670+ :param connect_server: the Connect server information.
671+ :param directory: the app directory to deploy.
672+ :param extra_files: any extra files that should be included in the deploy.
673+ :param excludes: a sequence of glob patterns that will exclude matched files.
674+ :param entry_point: the module/executable object for the WSGi framework.
675+ :param new: a flag to force this as a new deploy.
676+ :param app_id: the ID of an existing application to deploy new files for.
677+ :param title: an optional title for the deploy. If this is not provided, ne will
678+ be generated.
679+ :param python: the optional name of a Python executable.
680+ :param conda_mode: use conda to build an environment.yml
681+ instead of conda, when conda is not supported on RStudio Connect (version<=1.8.0).
682+ :param force_generate: force generating "requirements.txt" or "environment.yml",
683+ even if it already exists.
684+ :param log_callback: the callback to use to write the log to. If this is None
685+ (the default) the lines from the deployment log will be returned as a sequence.
686+ If a log callback is provided, then None will be returned for the log lines part
687+ of the return tuple.
688+ :return: the ultimate URL where the deployed app may be accessed and the sequence
689+ of log lines. The log lines value will be None if a log callback was provided.
690+ """
691+ return _deploy_by_python_framework (
692+ connect_server ,
693+ directory ,
694+ extra_files ,
695+ excludes ,
696+ entry_point ,
697+ gather_basic_deployment_info_for_fastapi ,
698+ new ,
699+ app_id ,
700+ title ,
701+ python ,
702+ conda_mode ,
703+ force_generate ,
704+ log_callback ,
705+ )
706+
707+
628708def deploy_dash_app (
629709 connect_server ,
630710 directory ,
@@ -836,10 +916,20 @@ def _deploy_by_python_framework(
836916 """
837917 module_file = fake_module_file_from_directory (directory )
838918 app_store = AppStore (module_file )
839- (entry_point , app_id , deployment_name , deployment_title , default_title , app_mode ,) = gatherer (
840- connect_server , app_store , directory , entry_point , new , app_id , title
919+ (
920+ entry_point ,
921+ app_id ,
922+ deployment_name ,
923+ deployment_title ,
924+ default_title ,
925+ app_mode ,
926+ ) = gatherer (connect_server , app_store , directory , entry_point , new , app_id , title )
927+ _ , environment = get_python_env_info (
928+ directory ,
929+ python ,
930+ conda_mode = conda_mode ,
931+ force_generate = force_generate ,
841932 )
842- _ , environment = get_python_env_info (directory , python , conda_mode = conda_mode , force_generate = force_generate ,)
843933 bundle = create_api_deployment_bundle (directory , extra_files , excludes , entry_point , app_mode , environment )
844934 return _finalize_deploy (
845935 connect_server ,
@@ -856,7 +946,12 @@ def _deploy_by_python_framework(
856946
857947
858948def deploy_by_manifest (
859- connect_server , manifest_file_name , new = False , app_id = None , title = None , log_callback = None ,
949+ connect_server ,
950+ manifest_file_name ,
951+ new = False ,
952+ app_id = None ,
953+ title = None ,
954+ log_callback = None ,
860955):
861956 """
862957 A function to deploy a Jupyter notebook to Connect. Depending on the files involved
@@ -1003,13 +1098,21 @@ def _generate_gather_basic_deployment_info_for_python(app_mode):
10031098
10041099 def gatherer (connect_server , app_store , directory , entry_point , new , app_id , title ):
10051100 return _gather_basic_deployment_info_for_framework (
1006- connect_server , app_store , directory , entry_point , new , app_id , app_mode , title ,
1101+ connect_server ,
1102+ app_store ,
1103+ directory ,
1104+ entry_point ,
1105+ new ,
1106+ app_id ,
1107+ app_mode ,
1108+ title ,
10071109 )
10081110
10091111 return gatherer
10101112
10111113
10121114gather_basic_deployment_info_for_api = _generate_gather_basic_deployment_info_for_python (AppModes .PYTHON_API )
1115+ gather_basic_deployment_info_for_fastapi = _generate_gather_basic_deployment_info_for_python (AppModes .PYTHON_FASTAPI )
10131116gather_basic_deployment_info_for_dash = _generate_gather_basic_deployment_info_for_python (AppModes .DASH_APP )
10141117gather_basic_deployment_info_for_streamlit = _generate_gather_basic_deployment_info_for_python (AppModes .STREAMLIT_APP )
10151118gather_basic_deployment_info_for_bokeh = _generate_gather_basic_deployment_info_for_python (AppModes .BOKEH_APP )
@@ -1102,7 +1205,12 @@ def get_python_env_info(file_name, python, conda_mode=False, force_generate=Fals
11021205
11031206
11041207def create_notebook_deployment_bundle (
1105- file_name , extra_files , app_mode , python , environment , extra_files_need_validating = True ,
1208+ file_name ,
1209+ extra_files ,
1210+ app_mode ,
1211+ python ,
1212+ environment ,
1213+ extra_files_need_validating = True ,
11061214 hide_all_input = None ,
11071215 hide_tagged_input = None ,
11081216):
@@ -1116,7 +1224,7 @@ def create_notebook_deployment_bundle(
11161224 :param environment: environmental information.
11171225 :param extra_files_need_validating: a flag indicating whether the list of extra
11181226 :param hide_all_input: if True, will hide all input cells when rendering output
1119- :param hide_tagged_input: If True, will hide input code cells with the 'hide_input' tag when rendering output
1227+ :param hide_tagged_input: If True, will hide input code cells with the 'hide_input' tag when rendering output
11201228 files should be validated or not. Part of validating includes qualifying each
11211229 with the parent directory of the notebook file. If you provide False here, make
11221230 sure the names are properly qualified first.
@@ -1139,7 +1247,13 @@ def create_notebook_deployment_bundle(
11391247
11401248
11411249def create_api_deployment_bundle (
1142- directory , extra_files , excludes , entry_point , app_mode , environment , extra_files_need_validating = True ,
1250+ directory ,
1251+ extra_files ,
1252+ excludes ,
1253+ entry_point ,
1254+ app_mode ,
1255+ environment ,
1256+ extra_files_need_validating = True ,
11431257):
11441258 """
11451259 Create an in-memory bundle, ready to deploy.
@@ -1223,17 +1337,21 @@ def create_notebook_manifest_and_environment_file(
12231337 :param force: if True, forces the environment file to be written. even if it
12241338 already exists.
12251339 :param hide_all_input: if True, will hide all input cells when rendering output
1226- :param hide_tagged_input: If True, will hide input code cells with the 'hide_input' tag when rendering output
1340+ :param hide_tagged_input: If True, will hide input code cells with the 'hide_input' tag when rendering output
12271341 :return:
12281342 """
12291343 if (
1230- not write_notebook_manifest_json (entry_point_file , environment , app_mode , extra_files , hide_all_input , hide_tagged_input )
1344+ not write_notebook_manifest_json (
1345+ entry_point_file , environment , app_mode , extra_files , hide_all_input , hide_tagged_input
1346+ )
12311347 or force
12321348 ):
12331349 write_environment_file (environment , dirname (entry_point_file ))
12341350
12351351
1236- def write_notebook_manifest_json (entry_point_file , environment , app_mode , extra_files , hide_all_input , hide_tagged_input ):
1352+ def write_notebook_manifest_json (
1353+ entry_point_file , environment , app_mode , extra_files , hide_all_input , hide_tagged_input
1354+ ):
12371355 """
12381356 Creates and writes a manifest.json file for the given entry point file. If
12391357 the application mode is not provided, an attempt will be made to resolve one
@@ -1247,7 +1365,7 @@ def write_notebook_manifest_json(entry_point_file, environment, app_mode, extra_
12471365 portion of the entry point file name will be used to derive one.
12481366 :param extra_files: any extra files that should be included in the manifest.
12491367 :param hide_all_input: if True, will hide all input cells when rendering output
1250- :param hide_tagged_input: If True, will hide input code cells with the 'hide_input' tag when rendering output
1368+ :param hide_tagged_input: If True, will hide input code cells with the 'hide_input' tag when rendering output
12511369 :return: whether or not the environment file (requirements.txt, environment.yml,
12521370 etc.) that goes along with the manifest exists.
12531371 """
@@ -1276,7 +1394,13 @@ def write_notebook_manifest_json(entry_point_file, environment, app_mode, extra_
12761394
12771395
12781396def create_api_manifest_and_environment_file (
1279- directory , entry_point , environment , app_mode = AppModes .PYTHON_API , extra_files = None , excludes = None , force = True ,
1397+ directory ,
1398+ entry_point ,
1399+ environment ,
1400+ app_mode = AppModes .PYTHON_API ,
1401+ extra_files = None ,
1402+ excludes = None ,
1403+ force = True ,
12801404):
12811405 """
12821406 Creates and writes a manifest.json file for the given Python API entry point. If
@@ -1299,7 +1423,12 @@ def create_api_manifest_and_environment_file(
12991423
13001424
13011425def write_api_manifest_json (
1302- directory , entry_point , environment , app_mode = AppModes .PYTHON_API , extra_files = None , excludes = None ,
1426+ directory ,
1427+ entry_point ,
1428+ environment ,
1429+ app_mode = AppModes .PYTHON_API ,
1430+ extra_files = None ,
1431+ excludes = None ,
13031432):
13041433 """
13051434 Creates and writes a manifest.json file for the given entry point file. If
0 commit comments