Skip to content

Commit 2affe0f

Browse files
committed
Adds 'flask', 'asgi', and 'wsgi' options as aliases to 'api' and 'fastapi'.
1 parent 5735415 commit 2affe0f

File tree

3 files changed

+74
-45
lines changed

3 files changed

+74
-45
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
33

44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6+
67
## Unreleased
78

89
### Fixed
@@ -20,6 +21,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2021
and `*_app.py` are now considered. However, if the directory contains more than
2122
one file matching these new patterns, you must provide rsconnect-python with an
2223
explicit `--entrypoint` argument.
24+
- Added the `deploy asgi` command.
25+
- Added the `deploy flask` command.
26+
- Added the `deploy wsgi` command.
27+
- Added the `deploy asgi` command.
28+
- Added the `deploy wsgi` command.
29+
- Added the `deploy flask` command.
30+
31+
### Removed
32+
- Deprecated the `deploy api` command.
33+
- Deprecated the `write-manifest api` command.
2334

2435
## [1.20.0] - 2023-09-11
2536

README.md

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ you will need to include the `--cacert` option that points to your certificate
117117
authority (CA) trusted certificates file. Both of these options can be saved along
118118
with the URL and API Key for a server.
119119

120-
> **Note**
120+
> **Note**
121121
> When certificate information is saved for the server, the specified file
122122
> is read and its _contents_ are saved under the server's nickname. If the CA file's
123123
> contents are ever changed, you will need to add the server information again.
@@ -135,7 +135,7 @@ rsconnect add \
135135
--name myserver
136136
```
137137

138-
> **Note**
138+
> **Note**
139139
> The `rsconnect` CLI will verify that the serve URL and API key
140140
> are valid. If either is found not to be, no information will be saved.
141141
@@ -270,14 +270,13 @@ rsconnect write-manifest notebook my-notebook.ipynb
270270
You can deploy a variety of APIs and applications using sub-commands of the
271271
`rsconnect deploy` command.
272272

273-
* `api`: WSGI-compliant APIs such as Flask and packages based on Flask
274-
* `fastapi`: ASGI-compliant APIs (FastAPI, Quart, Sanic, and Falcon)
275-
* `dash`: Python Dash apps
276-
* `streamlit`: Streamlit apps
277-
* `bokeh`: Bokeh server apps
278-
279-
All options below apply equally to the `api`, `fastapi`, `dash`, `streamlit`,
280-
and `bokeh` sub-commands.
273+
* `wsgi`: [WSGI (PEP 3333)](https://peps.python.org/pep-3333/) compliant applications such as Bottle, Flask, and Pycnic.
274+
* `asgi`: [ASGI](https://asgi.readthedocs.io/en/latest/specs/main.html) compliant applications such as Falcon, FastAPI, Quart, and Sanic.
275+
* `bokeh`: Bokeh server applications.
276+
* `dash`: Dash appliations.
277+
* `fastapi`: FastAPI applications.
278+
* `flask`: Flask applications.
279+
* `streamlit`: Streamlit applications.
281280

282281
#### Including Extra Files
283282

@@ -286,7 +285,7 @@ API or application is run by the Posit Connect server. Just specify them on the
286285
command line after the API or application directory:
287286

288287
```bash
289-
rsconnect deploy api flask-api/ data.csv
288+
rsconnect deploy flask flask-api/ data.csv
290289
```
291290

292291
Since deploying an API or application starts at a directory level, there will be times
@@ -351,7 +350,7 @@ the package dependencies will be determined from the current Python environment,
351350
from an alternative Python executable specified via the `--python` option:
352351

353352
```bash
354-
rsconnect deploy api --python /path/to/python my-api/
353+
rsconnect deploy wsgi --python /path/to/python my-api/
355354
```
356355

357356
You can see the packages list that will be included by running `pip list --format=freeze` yourself,
@@ -374,7 +373,7 @@ Python executable specified in the `--python` option.
374373
Here is an example of the `write-manifest` command:
375374

376375
```bash
377-
rsconnect write-manifest api my-api/
376+
rsconnect write-manifest wsgi my-api/
378377
```
379378

380379
### Deploying R or Other Content
@@ -421,7 +420,7 @@ this, use the `--title` option:
421420
rsconnect deploy notebook --title "My Notebook" my-notebook.ipynb
422421
```
423422

424-
When using `rsconnect deploy api`, `rsconnect deploy fastapi`, `rsconnect deploy dash`,
423+
When using `rsconnect deploy wsgi`, `rsconnect deploy asgi`, `rsconnect deploy flask`, `rsconnect deploy fastapi`, `rsconnect deploy dash`,
425424
`rsconnect deploy streamlit`, or `rsconnect deploy bokeh`, the title is derived from the directory
426425
containing the API or application.
427426

@@ -430,7 +429,7 @@ filename referenced in the manifest.
430429

431430
### Environment variables
432431
You can set environment variables during deployment. Their names and values will be
433-
passed to Posit Connect during deployment so you can use them in your code. Note that
432+
passed to Posit Connect during deployment so you can use them in your code. Note that
434433
if you are using `rsconnect` to deploy to shinyapps.io, environment variable management
435434
is not supported on that platform.
436435

@@ -985,9 +984,9 @@ xargs printf -- '-g %s\n' < guids.txt | xargs rsconnect content build add
985984
```
986985
## Programmatic Provisioning
987986
988-
Posit Connect supports the programmatic bootstrapping of an administrator API key
987+
Posit Connect supports the programmatic bootstrapping of an administrator API key
989988
for scripted provisioning tasks. This process is supported by the `rsconnect bootstrap` command,
990-
which uses a JSON Web Token to request an initial API key from a fresh Connect instance.
989+
which uses a JSON Web Token to request an initial API key from a fresh Connect instance.
991990
992991
> **Warning**
993992
> This feature **requires Python version 3.6 or higher**.
@@ -998,7 +997,7 @@ rsconnect bootstrap \
998997
--jwt-keypath /path/to/secret.key
999998
```
1000999
1001-
A full description on how to use `rsconnect bootstrap` in a provisioning workflow is provided in the Connect administrator guide's
1000+
A full description on how to use `rsconnect bootstrap` in a provisioning workflow is provided in the Connect administrator guide's
10021001
[programmatic provisioning](https://docs.posit.co/connect/admin/programmatic-provisioning) documentation.
10031002
10041003
## Server Administration Tasks

rsconnect/main.py

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import click
99
from os.path import abspath, dirname, exists, isdir, join
1010
from functools import wraps
11+
from typing import Optional
1112

1213
from rsconnect.certificates import read_certificate_file
1314

@@ -65,6 +66,7 @@
6566
from .log import logger, LogOutputFormat
6667
from .metadata import ServerStore, AppStore
6768
from .models import (
69+
AppMode,
6870
AppModes,
6971
BuildStatus,
7072
ContentGuidWithBundleParamType,
@@ -1281,19 +1283,28 @@ def deploy_html(
12811283
)
12821284

12831285

1284-
def generate_deploy_python(app_mode, alias, min_version):
1286+
def generate_deploy_python(app_mode: AppMode, alias: str, min_version: str, deprecated: bool = False, desc: Optional[str] = None):
1287+
1288+
if desc is None:
1289+
desc = app_mode.desc()
1290+
1291+
help=(
1292+
"Deploy a {desc} module to Posit Connect, Posit Cloud, or shinyapps.io (if supported by the platform). "
1293+
'The "directory" argument must refer to an existing directory that contains the application code.'
1294+
).format(desc=desc)
1295+
1296+
short_help="Deploy a {desc} to Posit Connect [v{version}+], Posit Cloud, or shinyapps.io.".format(
1297+
desc=desc,
1298+
version=min_version,
1299+
)
1300+
12851301
# noinspection SpellCheckingInspection
12861302
@deploy.command(
12871303
name=alias,
1288-
short_help="Deploy a {desc} to Posit Connect [v{version}+], Posit Cloud, or shinyapps.io.".format(
1289-
desc=app_mode.desc(),
1290-
version=min_version,
1291-
),
1292-
help=(
1293-
"Deploy a {desc} module to Posit Connect, Posit Cloud, or shinyapps.io (if supported by the platform). "
1294-
'The "directory" argument must refer to an existing directory that contains the application code.'
1295-
).format(desc=app_mode.desc()),
1304+
short_help=short_help,
1305+
help=help,
12961306
no_args_is_help=True,
1307+
deprecated=deprecated,
12971308
)
12981309
@server_args
12991310
@content_args
@@ -1407,14 +1418,15 @@ def deploy_app(
14071418
return deploy_app
14081419

14091420

1410-
deploy_api = generate_deploy_python(app_mode=AppModes.PYTHON_API, alias="api", min_version="1.8.2")
1411-
# TODO: set fastapi min_version correctly
1412-
# deploy_fastapi = generate_deploy_python(app_mode=AppModes.PYTHON_FASTAPI, alias="fastapi", min_version="2021.08.0")
1413-
deploy_fastapi = generate_deploy_python(app_mode=AppModes.PYTHON_FASTAPI, alias="fastapi", min_version="2021.08.0")
1414-
deploy_dash_app = generate_deploy_python(app_mode=AppModes.DASH_APP, alias="dash", min_version="1.8.2")
1415-
deploy_streamlit_app = generate_deploy_python(app_mode=AppModes.STREAMLIT_APP, alias="streamlit", min_version="1.8.4")
1416-
deploy_bokeh_app = generate_deploy_python(app_mode=AppModes.BOKEH_APP, alias="bokeh", min_version="1.8.4")
1417-
deploy_shiny = generate_deploy_python(app_mode=AppModes.PYTHON_SHINY, alias="shiny", min_version="2022.07.0")
1421+
generate_deploy_python(app_mode=AppModes.PYTHON_API, alias="api", min_version="1.8.2", desc="API Application", deprecated=True)
1422+
generate_deploy_python(app_mode=AppModes.PYTHON_API, alias="wsgi", min_version="1.8.2", desc="WSGI Application")
1423+
generate_deploy_python(app_mode=AppModes.PYTHON_API, alias="flask", min_version="1.8.2", desc="Flask Application")
1424+
generate_deploy_python(app_mode=AppModes.PYTHON_FASTAPI, alias="asgi", min_version="2021.08.0", desc="ASGI Application")
1425+
generate_deploy_python(app_mode=AppModes.PYTHON_FASTAPI, alias="fastapi", min_version="2021.08.0", desc="FastAPI Application")
1426+
generate_deploy_python(app_mode=AppModes.DASH_APP, alias="dash", min_version="1.8.2")
1427+
generate_deploy_python(app_mode=AppModes.STREAMLIT_APP, alias="streamlit", min_version="1.8.4")
1428+
generate_deploy_python(app_mode=AppModes.BOKEH_APP, alias="bokeh", min_version="1.8.4")
1429+
generate_deploy_python(app_mode=AppModes.PYTHON_SHINY, alias="shiny", min_version="2022.07.0")
14181430

14191431

14201432
@deploy.command(
@@ -1759,24 +1771,28 @@ def write_manifest_quarto(
17591771
)
17601772

17611773

1762-
def generate_write_manifest_python(app_mode, alias):
1774+
def generate_write_manifest_python(app_mode, alias, desc: Optional[str] = None, deprecated: bool = False):
1775+
if desc is None:
1776+
desc = app_mode.desc()
1777+
17631778
# noinspection SpellCheckingInspection
17641779
@write_manifest.command(
17651780
name=alias,
1766-
short_help="Create a manifest.json file for a {desc}.".format(desc=app_mode.desc()),
1781+
short_help="Create a manifest.json file for a {desc}.".format(desc=desc),
17671782
help=(
17681783
"Create a manifest.json file for a {desc} for later deployment. This will create an "
17691784
'environment file ("requirements.txt") if one does not exist. All files '
17701785
"are created in the same directory as the API code."
1771-
).format(desc=app_mode.desc()),
1786+
).format(desc=desc),
1787+
deprecated=deprecated,
17721788
)
17731789
@click.option("--overwrite", "-o", is_flag=True, help="Overwrite manifest.json, if it exists.")
17741790
@click.option(
17751791
"--entrypoint",
17761792
"-e",
17771793
help=(
17781794
"The module and executable object which serves as the entry point for the {desc} (defaults to app)"
1779-
).format(desc=app_mode.desc()),
1795+
).format(desc=desc),
17801796
)
17811797
@click.option(
17821798
"--exclude",
@@ -1850,12 +1866,15 @@ def manifest_writer(
18501866
return manifest_writer
18511867

18521868

1853-
write_manifest_api = generate_write_manifest_python(AppModes.PYTHON_API, alias="api")
1854-
write_manifest_fastapi = generate_write_manifest_python(AppModes.PYTHON_FASTAPI, alias="fastapi")
1855-
write_manifest_dash = generate_write_manifest_python(AppModes.DASH_APP, alias="dash")
1856-
write_manifest_streamlit = generate_write_manifest_python(AppModes.STREAMLIT_APP, alias="streamlit")
1857-
write_manifest_bokeh = generate_write_manifest_python(AppModes.BOKEH_APP, alias="bokeh")
1858-
write_manifest_shiny = generate_write_manifest_python(AppModes.PYTHON_SHINY, alias="shiny")
1869+
generate_write_manifest_python(AppModes.BOKEH_APP, alias="bokeh")
1870+
generate_write_manifest_python(AppModes.DASH_APP, alias="dash")
1871+
generate_write_manifest_python(AppModes.PYTHON_API, alias="api", desc="API Application", deprecated=True)
1872+
generate_write_manifest_python(AppModes.PYTHON_API, alias="wsgi", desc="WSGI Application")
1873+
generate_write_manifest_python(AppModes.PYTHON_API, alias="flask", desc="Flask Application")
1874+
generate_write_manifest_python(AppModes.PYTHON_FASTAPI, alias="asgi", desc="ASGI Application")
1875+
generate_write_manifest_python(AppModes.PYTHON_FASTAPI, alias="fastapi", desc="FastAPI Application")
1876+
generate_write_manifest_python(AppModes.PYTHON_SHINY, alias="shiny")
1877+
generate_write_manifest_python(AppModes.STREAMLIT_APP, alias="streamlit")
18591878

18601879

18611880
# noinspection SpellCheckingInspection

0 commit comments

Comments
 (0)