Skip to content

Commit c4e6e18

Browse files
authored
Merge pull request #1852 from rstudio/requirements-doc-improvements
Add `reg.finalizer(py_write_requirements)` example
2 parents 85be771 + 7c16ce2 commit c4e6e18

File tree

2 files changed

+84
-26
lines changed

2 files changed

+84
-26
lines changed

R/install.R

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -271,15 +271,39 @@ py_list_packages <- function(envname = NULL,
271271
#' ephemeral, it writes a fully resolved manifest via `pip freeze`.
272272
#'
273273
#' - `py_read_requirements()` reads `requirements.txt` and `.python-version`, and
274-
#' applies them with [py_require()]. By default, entries are added (`action =
275-
#' "add"`).
274+
#' applies them with [py_require()]. By default, entries are added (`action
275+
#' = "add"`).
276276
#'
277-
#' These are primarily an alternative interface to `py_require()`, but can also
278-
#' work with non-ephemeral virtual environments.
277+
#' These are primarily an alternative interface to `py_require()`, but can
278+
#' also work with non-ephemeral virtual environments.
279279
#'
280280
#' @note
281-
#' You can create a local virtual environment from `requirements.txt` and
282-
#' `.python-version` using [virtualenv_create()]:
281+
#'
282+
#' To continue using `py_require()` locally while keeping a
283+
#' `requirements.txt` up-to-date for deployments, you can register
284+
#' an exit handler in `.Rprofile` like this:
285+
#'
286+
#' ```r
287+
#' reg.finalizer(
288+
#' asNamespace("reticulate"),
289+
#' function(ns) {
290+
#' if (
291+
#' reticulate::py_available() &&
292+
#' isTRUE(reticulate::py_config()$ephemeral)
293+
#' ) {
294+
#' reticulate::py_write_requirements(quiet = TRUE)
295+
#' }
296+
#' },
297+
#' onexit = TRUE
298+
#' )
299+
#' ```
300+
#'
301+
#' This approach is only recommended if you are using `git`.
302+
#'
303+
#' Alternatively, you can transition away from using ephemeral python
304+
#' environemnts via `py_require()` to using a persistent local virtual
305+
#' environment you manage. You can create a local virtual environment from
306+
#' `requirements.txt` and `.python-version` using [virtualenv_create()]:
283307
#'
284308
#' ```r
285309
#' # Note: '.venv' in the current directory is auto-discovered by reticulate.
@@ -291,31 +315,37 @@ py_list_packages <- function(envname = NULL,
291315
#' )
292316
#' ```
293317
#'
318+
#' If you run into issues, be aware that `requirements.txt` and
319+
#' `.python-version` may not contain all the information necessary to
320+
#' reproduce the Python environment if the R code sets environment variables
321+
#' like `UV_INDEX` or `UV_CONSTRAINT`.
322+
#'
294323
#' @name py_requirements_files
295324
#'
296325
#' @param packages Path to the package requirements file. Defaults to
297326
#' `"requirements.txt"`. Use `NULL` to skip.
298327
#' @param python_version Path to the Python version file. Defaults to
299328
#' `".python-version"`. Use `NULL` to skip.
300-
#' @param freeze Logical. If `TRUE`, writes a fully resolved list of installed
301-
#' packages using `pip freeze`. If `FALSE`, writes only the requirements
302-
#' tracked by [py_require()].
329+
#' @param freeze Logical. If `TRUE`, writes a fully resolved list of
330+
#' installed packages using `pip freeze`. If `FALSE`, writes only the
331+
#' requirements tracked by [py_require()].
303332
#' @param python Path to the Python executable to use.
304333
#' @param action How to apply requirements read by `py_read_requirements()`:
305334
#' `"add"` (default) adds to existing requirements, `"set"` replaces them,
306-
#' `"remove"` removes matching entries, or `"none"` skips applying them and
307-
#' returns the read values.
335+
#' `"remove"` removes matching entries, or `"none"` skips applying them
336+
#' and returns the read values.
308337
#' @param ... Unused; must be empty.
309-
#' @param quiet Logical; if `TRUE`, suppresses the informational messages that
310-
#' print `wrote '<path>'` for each file written.
338+
#' @param quiet Logical; if `TRUE`, suppresses the informational messages
339+
#' that print `wrote '<path>'` for each file written.
311340
#'
312341
#' @return Invisibly, a list with two named elements:
313342
#' \describe{
314343
#' \item{`packages`}{Character vector of package requirements.}
315344
#' \item{`python_version`}{String specifying the Python version.}
316345
#' }
317346
#'
318-
#' To get just the return value without writing any files, you can pass `NULL` for file paths, like this:
347+
#' To get just the return value without writing any files, you can pass
348+
#' `NULL` for file paths, like this:
319349
#'
320350
#' ```r
321351
#' py_write_requirements(NULL, NULL)

man/py_requirements_files.Rd

Lines changed: 40 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)