rsconnect-python 1.30.0__tar.gz → 1.31.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/PKG-INFO +21 -3
  2. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/README.md +20 -2
  3. rsconnect_python-1.31.0/pyproject.toml +103 -0
  4. rsconnect_python-1.30.0/pyproject.toml → rsconnect_python-1.31.0/pyproject.toml.orig +1 -1
  5. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/actions.py +53 -11
  6. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/api.py +1805 -86
  7. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/bundle.py +2 -6
  8. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/certificates.py +18 -8
  9. rsconnect_python-1.31.0/rsconnect/connect_cloud.py +315 -0
  10. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/environment.py +8 -17
  11. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/http_support.py +171 -9
  12. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/json_web_token.py +1 -3
  13. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/log.py +18 -1
  14. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/main.py +536 -64
  15. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/metadata.py +233 -16
  16. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/models.py +34 -0
  17. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/oauth.py +251 -61
  18. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/shiny_express.py +9 -0
  19. rsconnect_python-1.31.0/rsconnect/validation.py +438 -0
  20. rsconnect_python-1.30.0/rsconnect/validation.py +0 -156
  21. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/LICENSE.md +0 -0
  22. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/__init__.py +0 -0
  23. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/actions_content.py +0 -0
  24. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/actions_environment.py +0 -0
  25. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/actions_integration.py +0 -0
  26. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/environment_node.py +0 -0
  27. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/environment_r.py +0 -0
  28. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/exception.py +0 -0
  29. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/git_metadata.py +0 -0
  30. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/py.typed +0 -0
  31. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/pyproject.py +0 -0
  32. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/__init__.py +0 -0
  33. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/quickstart.py +0 -0
  34. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/__init__.py +0 -0
  35. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/api/README.md.tmpl +0 -0
  36. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/api/__connect__.py.tmpl +0 -0
  37. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/api/__init__.py.tmpl +0 -0
  38. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/api/__main__.py.tmpl +0 -0
  39. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/api/app.py.tmpl +0 -0
  40. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/api/pyproject.toml.tmpl +0 -0
  41. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/fastapi/README.md.tmpl +0 -0
  42. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/fastapi/__connect__.py.tmpl +0 -0
  43. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/fastapi/__init__.py.tmpl +0 -0
  44. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/fastapi/__main__.py.tmpl +0 -0
  45. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/fastapi/app.py.tmpl +0 -0
  46. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/fastapi/pyproject.toml.tmpl +0 -0
  47. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/notebook/README.md.tmpl +0 -0
  48. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/notebook/notebook.ipynb.tmpl +0 -0
  49. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/notebook/pyproject.toml.tmpl +0 -0
  50. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/quarto/README.md.tmpl +0 -0
  51. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/quarto/pyproject.toml.tmpl +0 -0
  52. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/quarto/report.qmd.tmpl +0 -0
  53. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/shiny/README.md.tmpl +0 -0
  54. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/shiny/app.py.tmpl +0 -0
  55. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/shiny/pyproject.toml.tmpl +0 -0
  56. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/streamlit/README.md.tmpl +0 -0
  57. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/streamlit/app.py.tmpl +0 -0
  58. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/streamlit/pyproject.toml.tmpl +0 -0
  59. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/voila/README.md.tmpl +0 -0
  60. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/quickstart/templates/voila/pyproject.toml.tmpl +0 -0
  61. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/snowflake.py +0 -0
  62. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/subprocesses/__init__.py +0 -0
  63. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/subprocesses/inspect_environment.py +0 -0
  64. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/timeouts.py +0 -0
  65. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/utils_package.py +0 -0
  66. {rsconnect_python-1.30.0 → rsconnect_python-1.31.0}/rsconnect/version_check.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rsconnect_python
3
- Version: 1.30.0
3
+ Version: 1.31.0
4
4
  Summary: The Posit Connect command-line interface.
5
5
  Author: Posit, PBC
6
6
  Author-email: Posit, PBC <rsconnect@posit.co>
@@ -44,7 +44,7 @@ Description-Content-Type: text/markdown
44
44
 
45
45
  # [rsconnect-python](https://docs.posit.co/rsconnect-python)
46
46
 
47
- The [Posit Connect](https://docs.posit.co/connect/) command-line interface.
47
+ The command-line interface for [Posit Connect](https://docs.posit.co/connect/) and [Posit Connect Cloud](https://connect.posit.cloud).
48
48
 
49
49
  ## Installation
50
50
 
@@ -66,7 +66,7 @@ pipx install rsconnect-python
66
66
  python -m pip install rsconnect-python
67
67
  ```
68
68
 
69
- ## Usage
69
+ ## Usage with Posit Connect
70
70
 
71
71
  [Get an API key from your Posit Connect server](https://docs.posit.co/connect/user/api-keys/) with at least publisher privileges:
72
72
 
@@ -84,6 +84,24 @@ rsconnect deploy shiny app.py --title "my shiny app"
84
84
 
85
85
  [Read more about publisher and admin capabilities on the docs site.](https://docs.posit.co/rsconnect-python)
86
86
 
87
+ ## Usage with Posit Connect Cloud
88
+
89
+ Store your credentials, logging in to [Posit Connect Cloud](https://connect.posit.cloud) through your browser:
90
+
91
+ ```bash
92
+ rsconnect add --connect-cloud --account <YOUR-ACCOUNT-NAME> --name cloud
93
+ ```
94
+
95
+ Deploy your application:
96
+
97
+ ```bash
98
+ rsconnect deploy shiny app.py --name cloud --title "my shiny app"
99
+ ```
100
+
101
+ For non-interactive use such as CI, pass a service account credential with
102
+ `--client-id` and `--client-secret`, or the `CONNECT_CLOUD_CLIENT_ID` and
103
+ `CONNECT_CLOUD_CLIENT_SECRET` environment variables.
104
+
87
105
  ## Contributing
88
106
 
89
107
  [Contributing docs](./CONTRIBUTING.md)
@@ -1,6 +1,6 @@
1
1
  # [rsconnect-python](https://docs.posit.co/rsconnect-python)
2
2
 
3
- The [Posit Connect](https://docs.posit.co/connect/) command-line interface.
3
+ The command-line interface for [Posit Connect](https://docs.posit.co/connect/) and [Posit Connect Cloud](https://connect.posit.cloud).
4
4
 
5
5
  ## Installation
6
6
 
@@ -22,7 +22,7 @@ pipx install rsconnect-python
22
22
  python -m pip install rsconnect-python
23
23
  ```
24
24
 
25
- ## Usage
25
+ ## Usage with Posit Connect
26
26
 
27
27
  [Get an API key from your Posit Connect server](https://docs.posit.co/connect/user/api-keys/) with at least publisher privileges:
28
28
 
@@ -40,6 +40,24 @@ rsconnect deploy shiny app.py --title "my shiny app"
40
40
 
41
41
  [Read more about publisher and admin capabilities on the docs site.](https://docs.posit.co/rsconnect-python)
42
42
 
43
+ ## Usage with Posit Connect Cloud
44
+
45
+ Store your credentials, logging in to [Posit Connect Cloud](https://connect.posit.cloud) through your browser:
46
+
47
+ ```bash
48
+ rsconnect add --connect-cloud --account <YOUR-ACCOUNT-NAME> --name cloud
49
+ ```
50
+
51
+ Deploy your application:
52
+
53
+ ```bash
54
+ rsconnect deploy shiny app.py --name cloud --title "my shiny app"
55
+ ```
56
+
57
+ For non-interactive use such as CI, pass a service account credential with
58
+ `--client-id` and `--client-secret`, or the `CONNECT_CLOUD_CLIENT_ID` and
59
+ `CONNECT_CLOUD_CLIENT_SECRET` environment variables.
60
+
43
61
  ## Contributing
44
62
 
45
63
  [Contributing docs](./CONTRIBUTING.md)
@@ -0,0 +1,103 @@
1
+ [project]
2
+ name = "rsconnect_python"
3
+ description = "The Posit Connect command-line interface."
4
+ requires-python = ">=3.8"
5
+ version = "1.31.0"
6
+ dependencies = [
7
+ "typing-extensions>=4.8.0",
8
+ "pip>=10.0.0",
9
+ "uv>=0.9.0",
10
+ "semver>=2.0.0,<4.0.0",
11
+ "pyjwt>=2.4.0",
12
+ "click>=8.0.0",
13
+ "packaging>=20.0",
14
+ "toml>=0.10; python_version < '3.11'",
15
+ ]
16
+
17
+ [[project.authors]]
18
+ name = "Posit, PBC"
19
+ email = "rsconnect@posit.co"
20
+
21
+ [project.license]
22
+ file = "LICENSE.md"
23
+
24
+ [project.readme]
25
+ file = "README.md"
26
+ content-type = "text/markdown"
27
+
28
+ [project.scripts]
29
+ rsconnect = "rsconnect.main:cli"
30
+
31
+ [project.optional-dependencies]
32
+ keyring = ["keyring>=23.0.0"]
33
+ snowflake = ["snowflake-cli"]
34
+
35
+ [project.urls]
36
+ Repository = "http://github.com/posit-dev/rsconnect-python"
37
+ Documentation = "https://docs.posit.co/rsconnect-python"
38
+
39
+ [dependency-groups]
40
+ test = [
41
+ "coverage",
42
+ "httpretty",
43
+ "ipykernel",
44
+ "nbconvert",
45
+ "pytest",
46
+ "pytest-cov",
47
+ "twine",
48
+ "types-Flask",
49
+ "ruff",
50
+ "pyright",
51
+ ]
52
+ docs = [
53
+ "mkdocs-material",
54
+ "mkdocs-click",
55
+ "pymdown-extensions",
56
+ "mkdocs-macros-plugin",
57
+ ]
58
+
59
+ [build-system]
60
+ requires = ["uv_build>=0.9.0,<0.13.0"]
61
+ build-backend = "uv_build"
62
+
63
+ [tool.ruff]
64
+ line-length = 120
65
+ extend-exclude = [
66
+ "rsconnect-build",
67
+ "rsconnect-build-test",
68
+ "tests/testdata",
69
+ ]
70
+
71
+ [tool.ruff.lint]
72
+ select = [
73
+ "E",
74
+ "F",
75
+ "W",
76
+ ]
77
+ ignore = [
78
+ "E203",
79
+ "E231",
80
+ "E302",
81
+ ]
82
+
83
+ [tool.ruff.lint.per-file-ignores]
84
+ "tests/test_metadata.py" = ["E501"]
85
+
86
+ [tool.pyright]
87
+ typeCheckingMode = "strict"
88
+ reportPrivateUsage = "none"
89
+ reportUnnecessaryIsInstance = "none"
90
+ reportUnnecessaryComparison = "none"
91
+
92
+ [tool.uv.build-backend]
93
+ module-name = "rsconnect"
94
+ module-root = ""
95
+
96
+ [tool.coverage.run]
97
+ omit = ["tests/*"]
98
+
99
+ [tool.pytest.ini_options]
100
+ markers = []
101
+ addopts = """
102
+ --ignore=tests/testdata
103
+ """
@@ -2,7 +2,7 @@
2
2
  name = "rsconnect_python"
3
3
  description = "The Posit Connect command-line interface."
4
4
  requires-python = ">=3.8"
5
- version = "1.30.0"
5
+ version = "1.31.0"
6
6
  dependencies = [ "typing-extensions>=4.8.0", "pip>=10.0.0", "uv>=0.9.0", "semver>=2.0.0,<4.0.0", "pyjwt>=2.4.0", "click>=8.0.0", "packaging>=20.0", "toml>=0.10; python_version < '3.11'",]
7
7
  [[project.authors]]
8
8
  name = "Posit, PBC"
@@ -13,7 +13,8 @@ import subprocess
13
13
  import sys
14
14
  import traceback
15
15
  import typing
16
- from os.path import basename, exists, join, relpath
16
+ from os.path import basename, exists, isdir, join, relpath
17
+ from pathlib import PurePath
17
18
  from typing import Optional, Sequence, cast
18
19
  from warnings import warn
19
20
 
@@ -39,7 +40,7 @@ from .bundle import (
39
40
  from .environment import Environment
40
41
  from .environment_r import REnvironment
41
42
  from .exception import RSConnectException
42
- from .log import VERBOSE, logger
43
+ from .log import VERBOSE, console_logger, logger
43
44
  from .models import AppMode, AppModes
44
45
 
45
46
  line_width = 45
@@ -58,6 +59,12 @@ def cli_feedback(label: str, stderr: bool = False):
58
59
  vs. internal errors (prefixed with 'Internal Error'). In verbose mode,
59
60
  tracebacks will be emitted for internal errors.
60
61
  """
62
+ if logger.quiet:
63
+ # Quiet mode: suppress the step label and [OK] line so stdout stays
64
+ # reserved for the content URL; errors are routed to stderr.
65
+ label = ""
66
+ stderr = True
67
+
61
68
  if label:
62
69
  pad = line_width - len(label)
63
70
  click.secho(label + "... " + " " * pad, nl=False, err=stderr)
@@ -85,17 +92,36 @@ def cli_feedback(label: str, stderr: bool = False):
85
92
  logger.set_in_feedback(False)
86
93
 
87
94
 
88
- def set_verbosity(verbose: int):
89
- """Set the verbosity level based on a passed flag
95
+ # Maps a verbosity level to the (RSLogger level, console_logger level) it sets.
96
+ # Level -1 is quiet: RSLogger drops its diagnostic lines below WARNING and
97
+ # console_logger drops the @cls_logged step labels and [OK] lines (emitted at
98
+ # INFO/DEBUG) below WARNING, while still letting its warnings (e.g. credential
99
+ # overlap) through to stderr, so only warnings/errors and the final content URL
100
+ # survive. Levels 0/1/2 are normal/verbose/debug; anything above 2 clamps to debug.
101
+ _VERBOSITY_LEVELS = {
102
+ -1: (logging.WARNING, logging.WARNING),
103
+ 0: (logging.INFO, logging.DEBUG),
104
+ 1: (VERBOSE, logging.DEBUG),
105
+ 2: (logging.DEBUG, logging.DEBUG),
106
+ }
107
+
108
+
109
+ def set_verbosity(verbose: int, quiet: bool = False):
110
+ """Set the verbosity level based on the passed flags
90
111
 
91
- :param verbose: boolean specifying verbose or not
112
+ :param verbose: verbosity count (0 = normal, 1 = verbose, 2+ = debug)
113
+ :param quiet: emit only the final content URL on stdout; warnings and errors still go to stderr
92
114
  """
93
- if verbose == 0:
94
- logger.setLevel(logging.INFO)
95
- elif verbose == 1:
96
- logger.setLevel(VERBOSE)
97
- else:
98
- logger.setLevel(logging.DEBUG)
115
+ level = -1 if quiet else min(verbose, 2)
116
+ logger_level, console_level = _VERBOSITY_LEVELS[level]
117
+ # Set quiet state (also undoing any left over from an earlier invocation in
118
+ # the same process) before validating the flags so that even the
119
+ # flag-conflict error below lands on stderr, not stdout.
120
+ logger.set_quiet(quiet)
121
+ logger.setLevel(logger_level)
122
+ console_logger.setLevel(console_level)
123
+ if quiet and verbose:
124
+ raise RSConnectException("--quiet cannot be used together with -v/--verbose.")
99
125
 
100
126
 
101
127
  def _verify_server(connect_server: api.RSConnectServer):
@@ -238,10 +264,15 @@ class QuartoInspectResultConfig(TypedDict):
238
264
  project: QuartoInspectResultConfigProject
239
265
 
240
266
 
267
+ class QuartoInspectResultFiles(TypedDict):
268
+ input: list[str]
269
+
270
+
241
271
  class QuartoInspectResult(TypedDict):
242
272
  quarto: QuartoInspectResultQuarto
243
273
  engines: list[str]
244
274
  config: NotRequired[QuartoInspectResultConfig]
275
+ files: NotRequired[QuartoInspectResultFiles]
245
276
 
246
277
 
247
278
  def quarto_inspect(
@@ -277,6 +308,17 @@ def validate_quarto_engines(inspect: QuartoInspectResult):
277
308
  return engines
278
309
 
279
310
 
311
+ def quarto_inputs_from_inspect(file_or_directory: str, inspect: QuartoInspectResult) -> list[str]:
312
+ """The project's render inputs relative to its root, in Quarto's render order.
313
+
314
+ Empty for a standalone document; its inspect output has no files section.
315
+ """
316
+ if not isdir(file_or_directory):
317
+ return []
318
+ inputs = inspect.get("files", {}).get("input", [])
319
+ return [PurePath(relpath(each, file_or_directory)).as_posix() for each in inputs]
320
+
321
+
280
322
  # ===============================================================================
281
323
  # START: Compatibility entry point used by the vetiver-python package.
282
324
  # vetiver's `deploy_connect` calls `deploy_python_fastapi` (below), which routes