Skip to content

Commit 996774c

Browse files
committed
support for parsing renv.lock
1 parent b28aa50 commit 996774c

7 files changed

Lines changed: 686 additions & 2 deletions

File tree

rsconnect/actions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
read_manifest_file,
3838
)
3939
from .environment import Environment
40+
from .environment_r import REnvironment
4041
from .exception import RSConnectException
4142
from .log import VERBOSE, logger
4243
from .models import AppMode, AppModes
@@ -500,6 +501,7 @@ def create_quarto_deployment_bundle(
500501
image: Optional[str] = None,
501502
env_management_py: Optional[bool] = None,
502503
env_management_r: Optional[bool] = None,
504+
r_environment: Optional[REnvironment] = None,
503505
) -> typing.IO[bytes]:
504506
"""
505507
Create an in-memory bundle, ready to deploy.
@@ -519,6 +521,7 @@ def create_quarto_deployment_bundle(
519521
The server administrator is responsible for installing packages in the runtime environment. Default = None.
520522
:param env_management_r: False prevents Connect from managing the R environment for this bundle.
521523
The server administrator is responsible for installing packages in the runtime environment. Default = None.
524+
:param r_environment: optional R dependencies detected from renv.lock to add to the manifest.
522525
:return: the bundle.
523526
"""
524527
if app_mode is None:
@@ -534,6 +537,7 @@ def create_quarto_deployment_bundle(
534537
image,
535538
env_management_py,
536539
env_management_r,
540+
r_environment,
537541
)
538542

539543

rsconnect/bundle.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454

5555
from .environment import Environment, list_environment_dirs, is_environment_dir
5656
from .environment_node import NodeEnvironment
57+
from .environment_r import REnvironment
5758
from .exception import RSConnectException
5859
from .log import VERBOSE, logger
5960
from .models import AppMode, AppModes, GlobSet
@@ -142,6 +143,12 @@ class ManifestDataNode(TypedDict):
142143
package_manager: ManifestDataNodePackageManager
143144

144145

146+
class ManifestDataRPackage(TypedDict):
147+
Source: str
148+
Repository: str
149+
description: dict[str, str]
150+
151+
145152
class ManifestData(TypedDict):
146153
version: int
147154
files: dict[str, ManifestDataFile]
@@ -151,6 +158,8 @@ class ManifestData(TypedDict):
151158
quarto: NotRequired[ManifestDataQuarto]
152159
python: NotRequired[ManifestDataPython]
153160
node: NotRequired[ManifestDataNode]
161+
platform: NotRequired[str]
162+
packages: NotRequired[dict[str, ManifestDataRPackage]]
154163
environment: NotRequired[ManifestDataEnvironment]
155164

156165

@@ -159,6 +168,7 @@ def __init__(
159168
self,
160169
version: Optional[int] = None,
161170
environment: Optional[Environment] = None,
171+
r_environment: Optional[REnvironment] = None,
162172
app_mode: Optional[AppMode] = None,
163173
entrypoint: Optional[str] = None,
164174
quarto_inspection: Optional[QuartoInspectResult] = None,
@@ -224,6 +234,10 @@ def __init__(
224234
manifest_environment = self.data.setdefault("environment", {})
225235
manifest_environment["python"] = {"requires": environment.python_version_requirement}
226236

237+
if r_environment:
238+
self.data["platform"] = r_environment.r_version
239+
self.data["packages"] = cast("dict[str, ManifestDataRPackage]", r_environment.packages)
240+
227241
if image or env_management_py is not None or env_management_r is not None:
228242
manifest_environment = self.data.setdefault("environment", {})
229243
if image:
@@ -410,10 +424,12 @@ def make_source_manifest(
410424
image: Optional[str] = None,
411425
env_management_py: Optional[bool] = None,
412426
env_management_r: Optional[bool] = None,
427+
r_environment: Optional[REnvironment] = None,
413428
) -> ManifestData:
414429
manifest: Manifest = Manifest(
415430
app_mode=app_mode,
416431
environment=environment,
432+
r_environment=r_environment,
417433
entrypoint=entrypoint,
418434
quarto_inspection=quarto_inspection,
419435
image=image,
@@ -597,10 +613,13 @@ def make_notebook_source_bundle(
597613
image: Optional[str] = None,
598614
env_management_py: Optional[bool] = None,
599615
env_management_r: Optional[bool] = None,
616+
r_environment: Optional[REnvironment] = None,
600617
) -> IO[bytes]:
601618
"""Create a bundle containing the specified notebook and python environment.
602619
603620
Returns a file-like object containing the bundle tarball.
621+
622+
:param r_environment: optional R dependencies detected from renv.lock to add to the manifest.
604623
"""
605624
if extra_files is None:
606625
extra_files = []
@@ -615,6 +634,7 @@ def make_notebook_source_bundle(
615634
image,
616635
env_management_py,
617636
env_management_r,
637+
r_environment,
618638
)
619639
if hide_all_input:
620640
if "jupyter" not in manifest:
@@ -660,12 +680,15 @@ def make_quarto_source_bundle(
660680
image: Optional[str] = None,
661681
env_management_py: Optional[bool] = None,
662682
env_management_r: Optional[bool] = None,
683+
r_environment: Optional[REnvironment] = None,
663684
) -> typing.IO[bytes]:
664685
"""
665686
Create a bundle containing the specified Quarto content and (optional)
666687
python environment.
667688
668689
Returns a file-like object containing the bundle tarball.
690+
691+
:param r_environment: optional R dependencies detected from renv.lock to add to the manifest.
669692
"""
670693
manifest, relevant_files = make_quarto_manifest(
671694
file_or_directory,
@@ -677,6 +700,7 @@ def make_quarto_source_bundle(
677700
image,
678701
env_management_py,
679702
env_management_r,
703+
r_environment,
680704
)
681705
bundle_file = tempfile.TemporaryFile(prefix="rsc_bundle")
682706

@@ -881,6 +905,7 @@ def make_api_manifest(
881905
image: Optional[str] = None,
882906
env_management_py: Optional[bool] = None,
883907
env_management_r: Optional[bool] = None,
908+
r_environment: Optional[REnvironment] = None,
884909
) -> tuple[ManifestData, list[str]]:
885910
"""
886911
Makes a manifest for an API.
@@ -896,6 +921,7 @@ def make_api_manifest(
896921
The server administrator is responsible for installing packages in the runtime environment. Default = None.
897922
:param env_management_r: False prevents Connect from managing the R environment for this bundle.
898923
The server administrator is responsible for installing packages in the runtime environment. Default = None.
924+
:param r_environment: optional R dependencies detected from renv.lock to add to the manifest.
899925
:return: the manifest and a list of the files involved.
900926
"""
901927
if is_environment_dir(directory):
@@ -920,6 +946,7 @@ def make_api_manifest(
920946
image,
921947
env_management_py,
922948
env_management_r,
949+
r_environment,
923950
)
924951

925952
manifest_add_buffer(manifest, environment.filename, environment.contents)
@@ -1268,6 +1295,7 @@ def make_voila_bundle(
12681295
image: Optional[str] = None,
12691296
env_management_py: Optional[bool] = None,
12701297
env_management_r: Optional[bool] = None,
1298+
r_environment: Optional[REnvironment] = None,
12711299
multi_notebook: bool = False,
12721300
) -> typing.IO[bytes]:
12731301
"""
@@ -1287,6 +1315,7 @@ def make_voila_bundle(
12871315
The server administrator is responsible for installing packages in the runtime environment. Default = None.
12881316
:param env_management_r: False prevents Connect from managing the R environment for this bundle.
12891317
The server administrator is responsible for installing packages in the runtime environment. Default = None.
1318+
:param r_environment: optional R dependencies detected from renv.lock to add to the manifest.
12901319
:return: a file-like object containing the bundle tarball.
12911320
"""
12921321

@@ -1300,6 +1329,7 @@ def make_voila_bundle(
13001329
image=image,
13011330
env_management_py=env_management_py,
13021331
env_management_r=env_management_r,
1332+
r_environment=r_environment,
13031333
multi_notebook=multi_notebook,
13041334
)
13051335

@@ -1334,6 +1364,7 @@ def make_api_bundle(
13341364
image: Optional[str] = None,
13351365
env_management_py: Optional[bool] = None,
13361366
env_management_r: Optional[bool] = None,
1367+
r_environment: Optional[REnvironment] = None,
13371368
) -> typing.IO[bytes]:
13381369
"""
13391370
Create an API bundle, given a directory path and a manifest.
@@ -1349,6 +1380,7 @@ def make_api_bundle(
13491380
The server administrator is responsible for installing packages in the runtime environment. Default = None.
13501381
:param env_management_r: False prevents Connect from managing the R environment for this bundle.
13511382
The server administrator is responsible for installing packages in the runtime environment. Default = None.
1383+
:param r_environment: optional R dependencies detected from renv.lock to add to the manifest.
13521384
:return: a file-like object containing the bundle tarball.
13531385
"""
13541386
manifest, relevant_files = make_api_manifest(
@@ -1361,6 +1393,7 @@ def make_api_bundle(
13611393
image,
13621394
env_management_py,
13631395
env_management_r,
1396+
r_environment,
13641397
)
13651398
bundle_file = tempfile.TemporaryFile(prefix="rsc_bundle")
13661399

@@ -1524,6 +1557,7 @@ def make_quarto_manifest(
15241557
image: Optional[str] = None,
15251558
env_management_py: Optional[bool] = None,
15261559
env_management_r: Optional[bool] = None,
1560+
r_environment: Optional[REnvironment] = None,
15271561
) -> tuple[ManifestData, list[str]]:
15281562
"""
15291563
Makes a manifest for a Quarto project.
@@ -1539,6 +1573,7 @@ def make_quarto_manifest(
15391573
The server administrator is responsible for installing packages in the runtime environment. Default = None.
15401574
:param env_management_r: False prevents Connect from managing the R environment for this bundle.
15411575
The server administrator is responsible for installing packages in the runtime environment. Default = None.
1576+
:param r_environment: optional R dependencies detected from renv.lock to add to the manifest.
15421577
:return: the manifest and a list of the files involved.
15431578
"""
15441579
if environment:
@@ -1587,6 +1622,7 @@ def make_quarto_manifest(
15871622
image,
15881623
env_management_py,
15891624
env_management_r,
1625+
r_environment,
15901626
)
15911627

15921628
if environment:
@@ -1848,12 +1884,14 @@ def write_notebook_manifest_json(
18481884
image: Optional[str] = None,
18491885
env_management_py: Optional[bool] = None,
18501886
env_management_r: Optional[bool] = None,
1887+
r_environment: Optional[REnvironment] = None,
18511888
) -> bool:
18521889
"""
18531890
Creates and writes a manifest.json file for the given entry point file. If
18541891
the application mode is not provided, an attempt will be made to resolve one
18551892
based on the extension portion of the entry point file.
18561893
1894+
:param r_environment: optional R dependencies detected from renv.lock to add to the manifest.
18571895
:param entry_point_file: the entry point file (Jupyter notebook, etc.) to build
18581896
the manifest for.
18591897
:param environment: the Python environment to start with. This should be what's
@@ -1891,6 +1929,7 @@ def write_notebook_manifest_json(
18911929
image,
18921930
env_management_py,
18931931
env_management_r,
1932+
r_environment,
18941933
)
18951934
if hide_all_input or hide_tagged_input:
18961935
if "jupyter" not in manifest_data:
@@ -1930,6 +1969,7 @@ def create_voila_manifest(
19301969
image: Optional[str] = None,
19311970
env_management_py: Optional[bool] = None,
19321971
env_management_r: Optional[bool] = None,
1972+
r_environment: Optional[REnvironment] = None,
19331973
multi_notebook: bool = False,
19341974
) -> Manifest:
19351975
"""
@@ -1949,6 +1989,7 @@ def create_voila_manifest(
19491989
The server administrator is responsible for installing packages in the runtime environment. Default = None.
19501990
:param env_management_r: False prevents Connect from managing the R environment for this bundle.
19511991
The server administrator is responsible for installing packages in the runtime environment. Default = None.
1992+
:param r_environment: optional R dependencies detected from renv.lock to add to the manifest.
19521993
:return: the manifest data structure.
19531994
"""
19541995
if not path:
@@ -1989,6 +2030,7 @@ def create_voila_manifest(
19892030
manifest = Manifest(
19902031
app_mode=AppModes.JUPYTER_VOILA,
19912032
environment=environment,
2033+
r_environment=r_environment,
19922034
entrypoint=entrypoint,
19932035
image=image,
19942036
env_management_py=env_management_py,
@@ -2017,6 +2059,7 @@ def write_voila_manifest_json(
20172059
image: Optional[str] = None,
20182060
env_management_py: Optional[bool] = None,
20192061
env_management_r: Optional[bool] = None,
2062+
r_environment: Optional[REnvironment] = None,
20202063
multi_notebook: bool = False,
20212064
) -> bool:
20222065
"""
@@ -2036,6 +2079,7 @@ def write_voila_manifest_json(
20362079
The server administrator is responsible for installing packages in the runtime environment. Default = None.
20372080
:param env_management_r: False prevents Connect from managing the R environment for this bundle.
20382081
The server administrator is responsible for installing packages in the runtime environment. Default = None.
2082+
:param r_environment: optional R dependencies detected from renv.lock to add to the manifest.
20392083
:return: whether the manifest was written.
20402084
"""
20412085
manifest = create_voila_manifest(
@@ -2048,6 +2092,7 @@ def write_voila_manifest_json(
20482092
image=image,
20492093
env_management_py=env_management_py,
20502094
env_management_r=env_management_r,
2095+
r_environment=r_environment,
20512096
multi_notebook=multi_notebook,
20522097
)
20532098

@@ -2123,6 +2168,7 @@ def write_api_manifest_json(
21232168
image: Optional[str] = None,
21242169
env_management_py: Optional[bool] = None,
21252170
env_management_r: Optional[bool] = None,
2171+
r_environment: Optional[REnvironment] = None,
21262172
) -> bool:
21272173
"""
21282174
Creates and writes a manifest.json file for the given entry point file. If
@@ -2141,6 +2187,7 @@ def write_api_manifest_json(
21412187
The server administrator is responsible for installing packages in the runtime environment. Default = None.
21422188
:param env_management_r: False prevents Connect from managing the R environment for this bundle.
21432189
The server administrator is responsible for installing packages in the runtime environment. Default = None.
2190+
:param r_environment: optional R dependencies detected from renv.lock to add to the manifest.
21442191
:return: whether or not the environment file (requirements.txt, environment.yml,
21452192
etc.) that goes along with the manifest exists.
21462193
"""
@@ -2155,6 +2202,7 @@ def write_api_manifest_json(
21552202
image,
21562203
env_management_py,
21572204
env_management_r,
2205+
r_environment,
21582206
)
21592207
manifest_path = join(directory, "manifest.json")
21602208

@@ -2249,6 +2297,7 @@ def write_quarto_manifest_json(
22492297
image: Optional[str] = None,
22502298
env_management_py: Optional[bool] = None,
22512299
env_management_r: Optional[bool] = None,
2300+
r_environment: Optional[REnvironment] = None,
22522301
) -> None:
22532302
"""
22542303
Creates and writes a manifest.json file for the given Quarto project.
@@ -2264,6 +2313,7 @@ def write_quarto_manifest_json(
22642313
The server administrator is responsible for installing packages in the runtime environment. Default = None.
22652314
:param env_management_r: False prevents Connect from managing the R environment for this bundle.
22662315
The server administrator is responsible for installing packages in the runtime environment. Default = None.
2316+
:param r_environment: optional R dependencies detected from renv.lock to add to the manifest.
22672317
"""
22682318

22692319
manifest, _ = make_quarto_manifest(
@@ -2276,6 +2326,7 @@ def write_quarto_manifest_json(
22762326
image,
22772327
env_management_py,
22782328
env_management_r,
2329+
r_environment,
22792330
)
22802331

22812332
base_dir = file_or_directory

0 commit comments

Comments
 (0)