Skip to content

Commit

Permalink
Merge db656ab into 1e6303f
Browse files Browse the repository at this point in the history
  • Loading branch information
pbulsink committed Oct 2, 2023
2 parents 1e6303f + db656ab commit fa986c4
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 133 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* Updated `plot_fastest()` to use `correct_track_ratio()`
* Added a function to help switch between cache choices (#170, #171)
* Ensured cache option had default (`"memory"`) (#181, #183)
* Simplified Python package `fastf1` installation (#187).
* Virtualenv and Conda environment management is up to the user now

# f1dataR 1.3.0

Expand Down
90 changes: 38 additions & 52 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -117,77 +117,63 @@ get_fastf1_version <- function() {
dplyr::filter(.data$package == "fastf1") %>%
dplyr::pull("version")
if (length(ver) == 0) {
cli::cli_warn("Ensure fastf1 python package is installed.\nPlease run this to install the most recent version:\nreticulate::py_install('fastf1')")
cli::cli_warn("Ensure {.pkg fastf1} Python package is installed.\nPlease run this to install the most recent version:\n{.code setup_fastf1()}")

Check warning on line 120 in R/utils.R

View check run for this annotation

Codecov / codecov/patch

R/utils.R#L120

Added line #L120 was not covered by tests
return(NA)
}
if (as.integer(substr(ver, start = 1, 1)) >= 3) {
return(3)
} else if (as.integer(substr(ver, start = 1, 1)) <= 2) {
cli::cli_inform("The Python package fastf1 was updated to v3 recently.\nPlease update the version on your system by running:\nreticulate::py_install('fastf1')\nFuture versions of f1dataR may not support fastf1 < v3.0.0")
cli::cli_inform("The Python package {.pgk fastf1} was updated to v3 recently.\nPlease update the version on your system by running:\n{.code setup_fastf1(newenv = TRUE)}\nFuture versions of {.pkg f1dataR} may not support {.pkg fastf1<3.0.0}.")
return(2)
} else {
return(NA)
}
}

# nocov start

#' Setup fastf1 connection
#'
#' @description Set up reticulate using some options from user (or defaults). Helps
#' solve `fastf1` issues - see the Setup FastF1 Connection vignette for more info
#' (run \code{vignette('setup_fastf1', 'f1dataR')}).
#' @param envname a name for the virtualenv or conda environment.
#' For virtualenv, if a name is passed, `reticulate` will use/create the environment in the
#' default location. Alternatively, if providing a full path, `reticulate` will use the specified location.
#' @param conda whether to use conda environments or virtualenvs. Default FALSE (i.e. virtualenv)
#' @description Installs or optionally updates `fastf1` Python package in the current active Python
#' environment/virtualenv/conda env.
#'
#' More information on how to manage complex environment needs can be read in the
#' \href{https://rstudio.github.io/reticulate/articles/python_dependencies.html}{reticulate docs}, and tools for
#' managing virtual environments are documented in \link[reticulate]{virtualenv-tools} and
#' \link[reticulate]{conda-tools}
#' @param ... Additional parameters to pass to \link[reticulate]{py_install}
#' @param envname Optionally pass an environment name used. Defaults to package default of `f1dataR_env`.
#' @param new_env Whether or not to completely remove and recreate the environment provided in `envname`. This will fix
#' any issues experienced by `fastf1` related to package dependencies.
#' @export
#' @return No return value, called to set up virtan enviroment for package
#' @return No return value, called to install or update `fastf1` Python package.
#' @examples
#' \dontrun{
#' # setup fastf1 connection with all defaults
#' # Install fastf1 into the currently active Python environment
#' setup_fastf1()
#'
#' # setup with a preexisting conda environment, with a specified name
#' setup_fastf1("example_conda_env", conda = TRUE)
#' # Reinstall fastf1 and recreate the environment.
#' setup_fastf1(envname = "f1dataR_env", new_env = TRUE)
#' }
setup_fastf1 <- function(envname = "f1dataRenv", conda = FALSE) {
conda_exists <- function() {
tryCatch(
{
reticulate::conda_version()
return(TRUE)
},
error = function(e) {
return(FALSE)
}
)
}
if (conda == FALSE) {
if (envname %in% reticulate::virtualenv_list()) {
reticulate::use_virtualenv(envname)
} else if (conda_exists() && envname %in% reticulate::conda_list()$name) {
cli::cli_abort("{.val envname} found in list of conda environments. Did you mean to use that?",
x = "Run the function again with {.param conda} = `TRUE`"
)
} else {
reticulate::virtualenv_create(envname = envname, packages = c("numpy", "fastf1"))
reticulate::use_virtualenv(envname)
}
} else {
if (!conda_exists()) {
cli::cli_abort("Conda is not installed on your system.",
i = "If you wish to use conda please run {.code reticulate::install_miniconda}."
)
}
if (envname %in% reticulate::conda_list()$name) {
reticulate::use_condaenv(envname)
} else if (envname %in% reticulate::virtualenv_list()) {
cli::cli_abort("{.val {envname}} found in list of virtualenv environments. Did you mean to use that?",
x = "Run the function again with {.param conda} = `FALSE`"
)
} else {
reticulate::conda_create(envname = envname, packages = c("numpy", "fastf1"))
reticulate::use_condaenv(envname)
}
setup_fastf1 <- function(..., envname = "f1dataR_env", new_env = identical(envname, "f1dataR_env")) {
if (new_env && virtualenv_exists(envname)) {
cli::cli_alert("The Python environment {.var {envname}} is being removed and rebuilt for {.pkg fastf1}f")
virtualenv_remove(envname)
}

cli::cli_inform("Installing {.pkg fastf1} in current Python environment: {.var {envname}}.")
reticulate::py_install("fastf1", envname = envname, ...)
}


#' @noRd
dummy <- function(){
#this function creates and cleans a dummy table to clear r cmd check notes for
#janitor, tibble and tidyr
dummy<-tibble::tibble("Dummy" = c(1:5, NA)) %>%
janitor::clean_names() %>%
tidyr::drop_na()
invisible(NULL)
}

# nocov end
1 change: 1 addition & 0 deletions R/zzz.R
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# nocov start
.onLoad <- function(libname, pkgname) {
reticulate::use_virtualenv("f1dataR_env", required = FALSE)
reticulate::configure_environment(pkgname)
# Based on how nflreadr handles caching. Thanks to Tan (github @tanho63) for the suggestions

Expand Down
33 changes: 21 additions & 12 deletions man/setup_fastf1.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 0 additions & 51 deletions tests/testthat/test-utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -32,54 +32,3 @@ test_that("utility functions work", {
c(12.345, 83.456, 45296.789, 12.3456)
)
})

test_that("setup-fastf1 works", {
skip_if_no_py()
skip_if_no_ff1()

# Set testing specific parameters - this disposes after the test finishes
# Note: The test suite can't delete the old fastf1_http_cache.sqlite file
# because python's process has it locked.
withr::local_file(file.path(tempdir(), "tst_setup"))
if (dir.exists(file.path(tempdir(), "tst_setup"))) {
unlink(file.path(tempdir(), "tst_setup"), recursive = TRUE, force = TRUE)
}
dir.create(file.path(tempdir(), "tst_setup"), recursive = TRUE)
withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_setup"))
withr::local_envvar(.new = list(
"WORKON_HOME" = file.path(tempdir(), "tst_setup"),
"RETICULATE_PYTHON" = NA
))
withr::defer(reticulate::virtualenv_remove(file.path(tempdir(), "tst_setup", "setup_venv"), confirm = FALSE))

expect_false("setup_venv" %in% reticulate::virtualenv_list())

# Different testing environments may or may not have preexisting selected/activated python venv or condaenv.
# This try(suppressWarnings()) set makes sure that the code is run, and we'll test for that which we care about
# (namely the creation of the venv) afterwards
try(suppressWarnings(setup_fastf1(file.path(tempdir(), "tst_setup", "setup_venv"), conda = FALSE)))

expect_true("setup_venv" %in% reticulate::virtualenv_list())

if (reticulate:::conda_installed()) {
# Workflow runners or CRAN tests might not have conda

withr::defer(reticulate::conda_remove("setup_conda"))

expect_error(
setup_fastf1("setup_venv", conda = TRUE),
"* found in list of virtualenv environments. Did you mean to use that?"
)
expect_false("setup_conda" %in% reticulate::conda_list()$name)

# Because we set the venv earlier, reticulate won't let you set a second active env without restarting R.
# Alternatively, we can wrap this in 'try' also.
expect_error(setup_fastf1("setup_conda", conda = TRUE), "*failed to initialize requested version of Python")
expect_true("setup_conda" %in% reticulate::conda_list()$name)

expect_error(
setup_fastf1("setup_conda", conda = FALSE),
"* found in list of conda environments. Did you mean to use that?"
)
}
})
24 changes: 6 additions & 18 deletions vignettes/setup_fastf1.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ This vignette briefly describes setting up the `f1dataR` package to work properl
the Python package [`FastF1`](https://docs.fastf1.dev/). This guide may help resolve some issues
that might arise when you get the following warning or error messages:

- `Ensure fastf1 python package is installed. Please run this to install the most recent version: reticulate::py_install('fastf1')`
- `Ensure fastf1 python package is installed. Please run this to install the most recent version: setup_fastf1()`
- `Error in if (get_fastf1_version() < 3) { :`
`missing value where TRUE/FALSE needed`

Expand Down Expand Up @@ -55,26 +55,14 @@ This will create a virtual environment using your system's default Python versio
and install `fastf1` in that python environment. It will also tell `reticulate` to use that
environment instead of just running in your main system. For more information on Python
environments read [this article (infoworld.com)](https://www.infoworld.com/article/3239675/virtualenv-and-venv-python-virtual-environments-explained.html).

## With a specific virtual environment (or conda environment)

If you're comfortable with virtual environments and/or have one already set up for
fastf1, you can specify a virtualenv name/directory with the above function. If it's
a Conda environment, setting the `conda` argument as true will use `reticulate`s
interface for that in lieu of the one for virtualenv.

```r
setup_fastf1(envname = [envname], conda = [T/F])
```

# Routine/Repeat Issues
# Repeat/Recurring Issues

If you have repeat issues with the package failing to connect to your proper environment,
then before calling `library(f1dataR)` or using specific functions through `::`, add the
following to your code (replacing the `envname` parameter with your actual envname):
you can force a complete recreation of the virtual environment by calling:

```r
reticulate::use_virtualenv(virtualenv = [envname])
setup_fastf1(new_env = TRUE)
```

If you've used a Conda environment, call `reticulate::use_condaenv()` instead.
If you've configured the package to use a custom environment name, the above function will require that name supplied as
the `envname` parameter.

0 comments on commit fa986c4

Please sign in to comment.