rstudio / pins-r

Pin, discover, and share resources
https://pins.rstudio.com
Other
316 stars 62 forks source link

Error: [EACCES] Failed to copy - Permission denied #601

Closed minimenchmuncher closed 1 year ago

minimenchmuncher commented 2 years ago

I'm attempting to wrap some of the functionality of pins, including versioning, within another package and so I am attempting to run some of of the pins within testthat. As part of that wrap, I'm trying to run tests using dummy data (here, just iris) and am getting an error message that permission was denied while copying the data.

Reprex

## this works just fine
PINBOARD <- pins::board_temp(versioned = TRUE)
pins::pin_write(PINBOARD, iris, "iris", versioned = TRUE)
#> Guessing `type = 'rds'`
#> Creating new version '20220310T171134Z-44b86'
#> Writing to pin 'iris'
## sleep so that I can get a 2nd version of the data in the pin
Sys.sleep(2)
pins::pin_write(PINBOARD, iris, "iris", versioned = TRUE)
#> Guessing `type = 'rds'`
#> Creating new version '20220310T171136Z-44b86'
#> Writing to pin 'iris'

## clear out the pins
pins::pin_delete(PINBOARD, "iris")
unlink(PINBOARD$path, recursive = TRUE)
rm(list = ls())

library(testthat)
test_that("board_temp within testthat test", {
  PINBOARD <- pins::board_temp(versioned = TRUE)
  pins::pin_write(PINBOARD, iris, "iris", versioned = TRUE)
  Sys.sleep(2)
  ## the error seems to be here, writing the 2nd version of the pin
  pins::pin_write(PINBOARD, iris, "iris", versioned = TRUE)
})
#> ── Error (<text>:19:3): board_temp within testthat test ────────────────────────
#> <EACCES/fs_error/error/condition>
#> Error: [EACCES] Failed to copy '/tmp/RtmpMLQVap/iris.rds' to '/tmp/RtmpMLQVap/pins-f290627881e6/iris/20120304T050607Z-ce8b0/iris.rds': permission denied
#> Backtrace:
#>  1. pins::pin_write(PINBOARD, iris, "iris", versioned = TRUE)
#>  3. pins:::pin_store.pins_board_folder(...)
#>  4. fs::file_copy(paths, version_dir, overwrite = TRUE)
#> Error:
#> ! Test failed

Created on 2022-03-10 by the reprex package (v2.0.1)

Session info ``` r sessioninfo::session_info() #> ─ Session info ─────────────────────────────────────────────────────────────── #> setting value #> version R version 4.1.2 (2021-11-01) #> os Ubuntu 21.10 #> system x86_64, linux-gnu #> ui X11 #> language (EN) #> collate en_US.UTF-8 #> ctype en_US.UTF-8 #> tz America/New_York #> date 2022-03-10 #> pandoc 2.17.1.1 @ /usr/lib/rstudio/bin/quarto/bin/ (via rmarkdown) #> #> ─ Packages ─────────────────────────────────────────────────────────────────── #> package * version date (UTC) lib source #> backports 1.4.1 2021-12-13 [1] RSPM (R 4.1.2) #> brio 1.1.3 2021-11-30 [1] RSPM (R 4.0.4) #> cli 3.2.0 2022-02-14 [1] RSPM (R 4.0.4) #> crayon 1.5.0 2022-02-14 [1] RSPM (R 4.0.4) #> desc 1.4.0 2021-09-28 [1] RSPM (R 4.0.4) #> digest 0.6.29 2021-12-01 [1] RSPM (R 4.0.4) #> ellipsis 0.3.2 2021-04-29 [1] RSPM (R 4.0.4) #> evaluate 0.15 2022-02-18 [1] RSPM (R 4.1.2) #> fansi 1.0.2 2022-01-14 [1] RSPM (R 4.0.4) #> fastmap 1.1.0 2021-01-25 [1] RSPM (R 4.0.4) #> fs 1.5.2 2021-12-08 [1] RSPM (R 4.0.4) #> glue 1.6.1 2022-01-22 [1] RSPM (R 4.0.4) #> highr 0.9 2021-04-16 [1] RSPM (R 4.0.4) #> htmltools 0.5.2 2021-08-25 [1] RSPM (R 4.1.2) #> knitr 1.37 2021-12-16 [1] RSPM (R 4.0.4) #> lifecycle 1.0.1 2021-09-24 [1] RSPM (R 4.0.4) #> magrittr 2.0.2 2022-01-26 [1] RSPM (R 4.0.4) #> pillar 1.7.0 2022-02-01 [1] RSPM (R 4.0.4) #> pins 1.0.1 2021-12-15 [1] RSPM (R 4.1.2) #> pkgconfig 2.0.3 2019-09-22 [1] RSPM (R 4.0.4) #> pkgload 1.2.4 2021-11-30 [1] RSPM (R 4.0.4) #> purrr 0.3.4 2020-04-17 [1] RSPM (R 4.0.4) #> R.cache 0.15.0 2021-04-30 [1] RSPM (R 4.1.2) #> R.methodsS3 1.8.1 2020-08-26 [1] RSPM (R 4.1.2) #> R.oo 1.24.0 2020-08-26 [1] RSPM (R 4.1.2) #> R.utils 2.11.0 2021-09-26 [1] RSPM (R 4.1.2) #> R6 2.5.1 2021-08-19 [1] RSPM (R 4.0.4) #> reprex 2.0.1 2021-08-05 [1] RSPM (R 4.1.2) #> rlang 1.0.1 2022-02-03 [1] RSPM (R 4.0.4) #> rmarkdown 2.12 2022-03-02 [1] RSPM (R 4.1.2) #> rprojroot 2.0.2 2020-11-15 [1] RSPM (R 4.0.4) #> rstudioapi 0.13 2020-11-12 [1] RSPM (R 4.0.4) #> sessioninfo 1.2.2 2021-12-06 [1] RSPM (R 4.0.4) #> stringi 1.7.6 2021-11-29 [1] RSPM (R 4.0.4) #> stringr 1.4.0 2019-02-10 [1] RSPM (R 4.0.4) #> styler 1.6.2 2021-09-23 [1] RSPM (R 4.1.2) #> testthat * 3.1.2 2022-01-20 [1] RSPM (R 4.0.4) #> tibble 3.1.6 2021-11-07 [1] RSPM (R 4.0.4) #> utf8 1.2.2 2021-07-24 [1] RSPM (R 4.0.4) #> vctrs 0.3.8 2021-04-29 [1] RSPM (R 4.0.4) #> withr 2.4.3 2021-11-30 [1] RSPM (R 4.0.4) #> xfun 0.29 2021-12-14 [1] RSPM (R 4.0.4) #> yaml 2.2.2 2022-01-25 [1] RSPM (R 4.0.4) #> #> [1] /home/ezra/R/x86_64-pc-linux-gnu-library/4.1 #> [2] /usr/local/lib/R/site-library #> [3] /usr/lib/R/site-library #> [4] /usr/lib/R/library #> #> ────────────────────────────────────────────────────────────────────────────── ```

What I'm attempting to do seems to work just fine run outside of the test, but does not work within test_that. I get the same error when this is part of a test suite and I use devtools::test(). Any assistance would be appreciated!

juliasilge commented 2 years ago

I can get the same error outside of a test without the Sys.sleep():

library(pins)
b <- board_temp(version = TRUE)
pin_write(b, iris)
#> Using `name = 'iris'`
#> Guessing `type = 'rds'`
#> Creating new version '20220310T234720Z-ace06'
#> Writing to pin 'iris'
pin_write(b, iris)
#> Using `name = 'iris'`
#> Guessing `type = 'rds'`
#> Creating new version '20220310T234720Z-ace06'
#> Error: [EACCES] Failed to copy '/var/folders/hv/hzsmmyk9393_m7q3nscx1slc0000gn/T/RtmpjHUpD9/iris.rds' to '/var/folders/hv/hzsmmyk9393_m7q3nscx1slc0000gn/T/RtmpjHUpD9/pins-7ab33a326f35/iris/20220310T234720Z-ace06/iris.rds': permission denied

Created on 2022-03-10 by the reprex package (v2.0.1)

minimenchmuncher commented 2 years ago

@juliasilge I have started looking into this issue; one thing to investigate is as to whether this issue you raise and the one I raise are in fact, the same issue. The purpose of Sys.sleep() was to ensure that pins would assign different version numbers because they go by time stamp, including seconds. In the example you gave, they were both assigned version 20220310T234720Z-ace06 because, presumably, they were created within one second of each other.

minimenchmuncher commented 2 years ago

Sincerest apologies @juliasilge - I spoke too soon! I believe these to be driven by the same issue, with your example showing actually much more clearly what's going on (for the first half of the issue, anyway).

In your example, both of the ids were assigned to 20220310T234720Z-ace06, and that's where I think the error is coming from. It looks like it's trying to write a version of iris.rds in a spot where one already exists. Here's a clear example of what's going on:

## another example
library(pins)
b <- board_temp(version = TRUE)
pin_write(b, iris)
#> Using `name = 'iris'`
#> Guessing `type = 'rds'`
#> Creating new version '20220311T152649Z-44b86'
#> Writing to pin 'iris'

## check the path for where iris.rds now lives:
iris_path <- pin_meta(b, "iris")$local$dir
file.exists(file.path(iris_path, "iris.rds"))
#> [1] TRUE

## print out the file path
cat(iris_path, "\n")
#> /tmp/Rtmp6WM9qJ/pins-2aee99ad7f4/iris/20220311T152649Z-44b86
pin_write(b, iris)
#> Using `name = 'iris'`
#> Guessing `type = 'rds'`
#> Creating new version '20220311T152649Z-44b86'
#> Error: [EACCES] Failed to copy '/tmp/Rtmp6WM9qJ/iris.rds' to '/tmp/Rtmp6WM9qJ/pins-2aee99ad7f4/iris/20220311T152649Z-44b86/iris.rds': permission denied

Created on 2022-03-11 by the reprex package (v2.0.1)

It looks like the "permission denied" error comes about because it's trying to overwrite a file (iris.rds) that already exists.

Now back to the original example, when I ran it outside of testthat, the IDs I was getting were 20220310T171134Z-44b86 and then 20220310T171136Z-44b86, a difference of 2 seconds, as a result of Sys.sleep(2). BUT, running inside testthat, the only id I was getting was 20120304T050607Z-ce8b0. Not sure what accounts for the difference. It looks like I can get around this issue, and do what I was trying to do, by making deep copies of iris in conjunction with Sys.sleep:

library(testthat)
test_that("board_temp within testthat test", {
  PINBOARD <- pins::board_temp(versioned = TRUE)
  ## write iris in once, as it is
  pins::pin_write(PINBOARD, iris, "iris", versioned = TRUE)
  Sys.sleep(2)

  ## this forces df1 to be a copy of iris
  df1 <- iris
  df1$Petal.Width <- df1$Petal.Width + 0

  pins::pin_write(PINBOARD, df1, "iris", versioned = TRUE)
  expect_true(TRUE)
})
#> Test passed 🥇

Created on 2022-03-11 by the reprex package (v2.0.1) Making a shallow copy (ie, just doing df1 <- iris) doesn't seem to work either. Not sure about using rlang::duplicate instead.

Here's what I propose:

  1. Issuing an error when it looks like the same ID is being used more than once. Edge case? perhaps-- except during tests. The error that fs gives is technically correct, but is unclear to the user what actually went wrong.
  2. Clarity as to why the ID for iris (or any other data set I've tried) is different when run within testthat, and why it isn't based on the current date/time. Much lower priority, but it is worrisome to me when functions behave differently within testthat from without.
juliasilge commented 1 year ago

Thanks for your patience on this @minimenchmuncher! What do you think about the proposed error message in #727?

github-actions[bot] commented 1 year ago

This issue has been automatically locked. If you believe you have found a related problem, please file a new issue (with a reprex: https://reprex.tidyverse.org) and link to this issue.