Skip to content

[R-pkg-devel] Checking package in Windows fails

4 messages · Ben Engbers, Ivan Krylov

#
Hi,

I have written a function which
- checks if the input is a raw-vector
- if the input is a file-descriptor, it converts the file-content to a 
raw-vector
- if the input is a URL, it converts the content to a raw vector
- if the input is a character-string, it is converted to a raw vector.

The URL-test relys on package pingr (line 17 in 'input_to_raw.R'). 
'is_online() tests if there is an internet-connection.
Line 18 tests if the URL is a valid URL. This test relys on the code in 
'Rex.R'. (I don't know why I have to explicitly include 'library("rex")' 
in the code since I have added rex to the Imports in the DESCRIPTION)

After incorporating this code in my package, the package passes all 
tests both under Linux as on Windows(10).

devtools::check_win_devel however returns with this error:

Error in curl::curl_fetch_memory(url, handle = h) :
   response reading failed

How can I solve this problem?

Ben

#' @title input_to_raw
#'
#' @return 'Raw' vector
#'
#' @param input Character vector length 1
#'
#' @description Convert \emph{input} to a length-1 character vector.
#'
#' @details If \emph{input} is a reference to a file, the number of bytes
#'     corresponding to the size is read. If it is an URL, the URL is 
read and converted to a 'Raw' vector.
#'     The function does not catch errors.
#'
#' @export

input_to_raw <- function(input) {
   type <- typeof(input)
   pi <- pingr::is_online()
   va <- grepl(re, input)
   switch (type,
           "raw"       = raw_input <- input,       # Raw
           "character" = {
             if (input == "") {                    # Empty input
               raw_input <- raw(0)
             } else if (file.exists(input)) {      # File on filesystem
               finfo <- file.info(input)
               toread <- file(input, "rb")
               raw_input <- readBin(toread, what = "raw", size = 1, n = 
finfo$size)
               close(toread)
             } else if (pi && va && (get_URL <- httr::GET(input))$status 
==200) {
               raw_input <- get_URL$content
             }
             else {                                # String
               raw_input <- charToRaw(input)
             }
           },
           default = stop("Unknown input-type, please report the type of 
the input."
          )
   )
   return(raw_input)
}

--------------

library("rex")

valid_chars <- rex::rex(except_some_of(".", "/", " ", "-"))

re <- rex::rex(
   start,
   # protocol identifier (optional) + //
   group(list("http", maybe("s")) %or% "ftp", "://"),
   # user:pass authentication (optional)
   maybe(non_spaces,
         maybe(":", zero_or_more(non_space)),
         "@"),
   #host name
   group(zero_or_more(valid_chars, zero_or_more("-")), 
one_or_more(valid_chars)),
   #domain name
   zero_or_more(".", zero_or_more(valid_chars, zero_or_more("-")), 
one_or_more(valid_chars)),
   #TLD identifier
   group(".", valid_chars %>% at_least(2)),
   # server port number (optional)
   maybe(":", digit %>% between(2, 5)),
   # resource path (optional)
   maybe("/", non_space %>% zero_or_more()),
   end
)
1 day later
#
On Mon, 15 Nov 2021 17:15:14 +0100
Ben Engbers <Ben.Engbers at Be-Logical.nl> wrote:

            
Have you added the corresponding importFrom(...) [1] commands to your
NAMESPACE file?
Theoretically, this invites a class of errors known as "time-of-check
to time-of-use" [2]: the user may go offline after the
pingr::is_online() check but before the httr::GET() request uses the
remote resource. But that's not what's causing you problems.

The problem here is that pingr's definition of "is online" differs from
"is able to fetch the URL you're testing", and I'm afraid it's
impossible to solve in the general sense. What you could do instead is
use tryCatch() to handle the error originating from curl and return
something else instead.

Or maybe letting the error propagate is the right idea. It may be bad
for reproducibility when a function silently returns something
completely different after the user goes offline. Then you would have
to handle the error in your tests instead of the function. A simple
option is wrapping the whole block of test code in try(), but that would
handle all errors, including real bugs.

A more complicated solution would be to handle the connection errors
specifically, construct error objects of class "connection_error",
signal them from the function and only handle those when testing via
tryCatch(..., connection_error = ...). This would let you both (1)
correctly propagate connection errors to the user instead of silently
returning the URL itself and (2) not crash the tests despite that.
See ?conditions for more information on that topic.
#
Thanks for your reply.

I have moved new/edited 'input_to_raw' code and the validation code to 
another file with all kind of utility-functions and that seems to have 
solved that problem. (But I don't understand why that helped ;-()

Hopefully then next version of my client will be using C++ to speed up 
reading from the socketConnection. And in that version I'll try to use 
tour suggestions. Since I am new to C++ that will take some time.

Ben

Op 16-11-2021 om 21:22 schreef Ivan Krylov:
I don't edit the NAMESPACE file by hand. It is created by roxygen2.