A sibling fyr-package composes the
two halves of the pyro contract: declare a dependency
group, then materialize it.
my_initialize <- function() {
pyro::write_group_to_pyproject(
name = "mypkg",
deps = c("pillow==11.1.0", "requests==2.31.0")
)
pyro::initialize_python(groups = "mypkg")
}The split between the two calls is deliberate.
write_group_to_pyproject() declares intent and stops there,
it returns without touching uv, Python, or the network, so it is safe to
call repeatedly and cheap to compose. Nothing is installed until
initialize_python() runs. That separation is what lets
several wrappers each register a group and then sync exactly once,
instead of every wrapper triggering its own resolve mid-chain.
deps is where pin ownership is decided. For a group
pyro already blesses (reportifyr,
presentifyr), omit it and the pins are read straight from
the bundled reference spec, the wrapper inherits whatever
pyro ships and stays in lockstep with it. Pass
deps explicitly and those become the project’s pins, with
pyro staying out of the way. A third-party app has no
blessed entry to fall back on, so it must always supply
deps.
venv_dir throughout the codebase means
the parent directory of .venv/ (i.e. the project
root when the venv lives at <project_root>/.venv/).
Preserved for compatibility with existing reportifyr and
presentifyr projects.pyproject_dir lets non-default project
layouts (LLM agents, monorepos, closed-source projects with a secret
toml elsewhere) point pyro at an alternate location. Must
already exist; pyro does not create project
directories.getOption("venv_dir") caches the
resolved project root after the first init; later calls in the same R
session skip re-resolution.getOption("uv.version") pins the uv
binary version. If unset, pyro uses whatever uv is already
installed, or falls back to 0.7.8 on a clean machine.