Giter VIP home page Giter VIP logo

arcgisutils's People

Contributors

josiahparry avatar kbvernon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

arcgisutils's Issues

Helpers for building SQL queries

I'm not sure whether these would belong here or in arcgislayers or wouldn't be of interest at all but I've been using a couple of helper functions that make creating queries for FeatureLayers much easier. These are the two I'm currently using most often:

ansi_in <- function(needle, haystack, ..., .envir = rlang::current_env(), .con = DBI::ANSI()) {
  glue::glue_sql(needle, " ", "IN", " ({haystack*})", ..., .envir = .envir, .con = .con)
}

sql_collapse <- function(x, sep = " AND ") {
  glue::glue_sql_collapse(x, sep = sep)
}

I think the same syntax rules described here also apply to the REST API: https://doc.arcgis.com/en/drone2map/latest/help/sql-reference-for-elements-used-in-query-expressions.htm

R arcgis fails to upload complex geometries in reliable way

Hi, so I have an issue where complex geometries fail to draw when they are uploaded to AGOL using the publish_layer()
feature. It appears that complex geometries have a significant difficulty loading when published to arcgis online.

Here is an example with some code that demonstrates this glaring issue in R while trying to pull down a public dataset involving CCRI:

`### Login to AGOL
token_AGOL <- auth_user(
username = "U",
password = "PW",
host = arc_host(),
expiration = 21600
)
set_arc_token(token_AGOL)

Pull Down CCRI

CCRI_URL = "https://services.arcgis.com/XG15cJAlne2vxtgt/arcgis/rest/services/Counties_FEMA_Community_Resilience_Challenges_Index_(CRCI)/FeatureServer/54"

Open Layer

CCRI_Layer <- arc_open(CCRI_URL)
CCRI_Layer

Use Arc Select to isolate the data

NY_CCRI_DF <- arc_select(CCRI_Layer,where = "STATEFP = '36'")
NY_CCRI_DF

Publish this data to arcgis online

res <- publish_layer(NY_CCRI_DF, "R-arcgisBridge Upload Test")
res
'

Unfortunately, once the shapefile is uploaded it collapses and fails to draw any of the more complex geometries - i.e. the entirety of long island

image

Within the Rstudio environment ,there is no issue with plotting the data.... via the command plot(NY_CCRI_DF)

image

The questions I have are:

  1. Can this issue be reproduced
  2. Are there any additional caveats to be considered when uploading data frames into AGOL
  3. If not, can a fix be issued? These are similar problems that occur with the arcgis api for python. As a positive critique I think there needs to be much more stress-testing with the R/python arcgis API suite in general. It's great to see examples of these features tested out on the square state of Colorado at the User Summit, but if it can't handle the very well-known region of Long Island this shouldn't have been released.

sanitize tokens that are empty strings?

When Sys.getenv("ARCGIS_TOKEN") returns an empty string, this will sometimes cause HTTP 498 "invalid token" error. Proposed solution is to empty the token with NULL.

Refreshing refresh token errors with bad subset

Reprex:

library(arcgisutils)
library(arcgislayers)
token <- auth_code()
# TODO why does the refresh token, not give another refresh here? 
refreshed <- refresh_token(token)

# BUG: refreshing a refreshed token errors!!!!!
refreshed |> refresh_token()

Helper to identify user portal information

portals <- arc_base_req(
  "https://arcgis.com/sharing/rest/portals/self",
  arc_token()
) |>
  req_body_form(f = "json") |> 
  req_perform() |> 
  resp_body_string() |> 
  RcppSimdJson::fparse()

This function will return a massive list that includes just about every piece of information you could possibly want to know about your user in your authorized portal.

library(httr2)
#> Warning: package 'httr2' was built under R version 4.3.1
library(arcgisutils)
#> Warning: package 'arcgisutils' was built under R version 4.3.1
portals <- arc_base_req(
  "https://arcgis.com/sharing/rest/portals/self",
  arc_token()
) |>
  req_body_form(f = "json") |> 
  req_perform() |> 
  resp_body_string() |> 
  RcppSimdJson::fparse()

names(portals)
#>  [1] "2DStylesGroupQuery"                "3DBasemapGalleryGroupQuery"       
#>  [3] "analysisLayersGroupQuery"          "basemapGalleryGroupQuery"         
#>  [5] "cdnUrl"                            "colorSetsGroupQuery"              
#>  [7] "contentCategorySetsGroupQuery"     "customBaseUrl"                    
#>  [9] "defaultBasemap"                    "defaultDevBasemap"                
#> [11] "defaultExtent"                     "defaultVectorBasemap"             
#> [13] "description"                       "devBasemapGalleryGroupQuery"      
#> [15] "featuredGroups"                    "featuredItemsGroupQuery"          
#> [17] "galleryTemplatesGroupQuery"        "helpBase"                         
#> [19] "helperServices"                    "homePageFeaturedContent"          
#> [21] "homePageFeaturedContentCount"      "isPortal"                         
#> [23] "layerTemplatesGroupQuery"          "livingAtlasGroupQuery"            
#> [25] "name"                              "portalHostname"                   
#> [27] "portalMode"                        "portalName"                       
#> [29] "portalThumbnail"                   "rasterFunctionTemplatesGroupQuery"
#> [31] "rotatorPanels"                     "staticImagesUrl"                  
#> [33] "stylesGroupQuery"                  "supports3DTilesServices"          
#> [35] "supportsHostedServices"            "symbolSetsGroupQuery"             
#> [37] "templatesGroupQuery"               "thumbnail"                        
#> [39] "use3dBasemaps"                     "useVectorBasemaps"                
#> [41] "vectorBasemapGalleryGroupQuery"    "httpPort"                         
#> [43] "httpsPort"                         "ipCntryCode"                      
#> [45] "supportsOAuth"                     "isReadOnly"                       
#> [47] "currentVersion"

Created on 2024-03-02 with reprex v2.0.2

bug: mapserver returning HTML instead of json when requested

To fix this we can modify fetch_layer_metadata() to this which adds f=json to the url and adds the token in the appropriate manner using req_auth_bearer_token().

fetch_layer_metadata <- function(request, token) {

  # add f=json to the url for querying
  req <- httr2::req_url_query(request, f = "json")

  # add the token
  req <- httr2::req_auth_bearer_token(req, token)

  # process the request and capture the response string
  resp_string <- httr2::resp_body_string(
    httr2::req_perform(req)
  )

  # process the response string
  meta <- RcppSimdJson::fparse(resp_string)

  # check if any errors occurred
  detect_errors(meta)

  # return the list
  meta
}

TODO:

  • add test for troublesome MapServer:
fetch_layer_metadata(httr2::request(furl),"")
  • ensure still works with known working MapServer https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer
  • ensure still works with services requiring auth

CC @kbvernon

obj_check_token error message should indicate how to create a token

As title describes. Current error message is below. Users might not know how to create an authorization token. The message should indicate how to create a token if needed.

arcgisutils::obj_check_token(NULL)
#> Error:
#> ! `token` must be an <httr2_token> not <NULL>
#> Backtrace:
#>     ▆
#>  1. └─arcgisutils::obj_check_token(NULL)
#>  2.   └─cli::cli_abort(...) at arcgisutils/R/arc-token.R:128:5
#>  3.     └─rlang::abort(...)

Created on 2024-03-20 with reprex v2.0.2

parse_esri_json() Cannot parse empty featureset

Maybe it could be useful that if there are no matches when using the filter_geom argument in the arc_read function, instead of an error, I get an empty dataset, just like when you do a filter in sf package with the query argument.

library(arcgislayers)

geojson <- '{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "coordinates": [
          [
            [
              -72.16260961974183,
              4.170524735334581
            ],
            [
              -72.16260961974183,
              3.5284018431919435
            ],
            [
              -71.25683279344358,
              3.5284018431919435
            ],
            [
              -71.25683279344358,
              4.170524735334581
            ],
            [
              -72.16260961974183,
              4.170524735334581
            ]
          ]
        ],
        "type": "Polygon"
      }
    }
  ]
}'

bbox <- geojsonsf::geojson_sf(geojson) |> sf::st_bbox()
url <- 'https://ags.esri.co/arcgis/rest/services/DatosAbiertos/PNN_2005/MapServer/0/'
data <- arc_read(url), filter_geom = bbox)

When I run that code, I get this error: Error in fts_raw[["attributes"]] : subíndice fuera de los límites

Add support for ArcGIS item and REST service URL validation and checks

For validation and handling of input URLs within {arcgislayers} and this package, it would be helpful to have a reliable set of url validation and checking functions.

This reprex is a first attempt at adapting and updating the existing URL checking and validation code from {esri2sf} for reuse in this package.

library(arcgisutils)
library(rlang)
#> 
#> Attaching package: 'rlang'
#> The following object is masked from 'package:arcgisutils':
#> 
#>     %||%

# Helper for setting URL pattern
set_url_pattern <- function(pattern = NULL, nm = NULL, collapse = "|") {
  if (is.null(pattern)) {
    return(pattern)
  }

  if (!is.null(nm)) {
    nm <- match.arg(nm, names(pattern))
    pattern <- pattern[nm]
  }

  paste0(pattern, collapse = collapse)
}

# Does x match the pattern of a URL?
# @noRd
is_url <- function(
    x,
    pattern = NULL,
    ...) {
  if (!is_vector(x) || is_empty(x)) {
    return(FALSE)
  }

  url_pattern <-
    "http[s]?://(?:[[:alnum:]]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+"

  if (is.null(pattern)) {
    return(grepl(url_pattern, x, ...))
  }

  pattern <- paste0(pattern, collapse = "|")

  grepl(url_pattern, x, ...) & grepl(pattern, x, ...)
}



# Check if x is a valid URL
# @noRd
check_url <- function(
    x,
    pattern = NULL,
    ...,
    allow_null = FALSE,
    message = NULL,
    arg = caller_arg(url),
    call = caller_env()) {
  if (allow_null && is.null(x)) {
    return(invisible(NULL))
  }

  if (is_url(x, pattern = pattern, ...)) {
    return(invisible(NULL))
  }

  check_string(
    x,
    allow_empty = FALSE,
    allow_null = allow_null,
    arg = arg,
    call = call
  )

  if (is.null(message)) {
    message <- "{.arg {arg}} must be a valid url,
    not {.obj_type_friendly {x}}."

    if (!is.null(pattern)) {
      message <- "{.arg {arg}} must be a valid url
    matching the pattern {.str {pattern}}"
    }
  }

  cli::cli_abort(
    message,
    call = call
  )
}

# Check if x is a string
# @noRd
check_string <- function(
    x,
    allow_empty = TRUE,
    allow_null = FALSE,
    arg = caller_arg(x),
    call = caller_env()
) {

  if (allow_null && is.null(x)) {
    return(invisible(NULL))
  }

  message <- "{.arg {arg}} must be a scalar character vector."

  if (is_scalar_character(x)) {
    if (allow_empty || x != "") {
      return(invisible(NULL))
    }

    message <- '{.arg {arg}} must be a non-empty string.'
  }

  cli::cli_abort(
    message,
    call = call
  )
}

# Vector of valid ESRI service types
esri_service_types <- c(
  "MapServer", "FeatureServer", "ImageServer", "GeoDataServer",
  "GeocodeServer", "GeometryServer", "GPServer", "WFSServer", "WFCServer"
)

# Named vector of ESRI service types
esri_service_type_patterns <- setNames(
  paste0("(?<=/rest/services).+/", esri_service_types, "/"),
  esri_service_types
)

# Vector of valid ESRI service types
esri_layer_types <- c(
  "FeatureLayer", "Table", "GroupLayer"
)

# Named vector of ESRI Item URL patterns
esri_item_url_patterns <- c(
  "content" = "/home/content\\.html\\?view=",
  "search" = "/home/search\\.html",
  "item" = "/home/item\\.html\\?id=",
  "group" = "/home/group\\.html\\?id=",
  "user" = "/home/user\\.html\\?user=",
  "scene" = "/home/webscene/viewer\\.html\\?webscene=",
  "app" = "/index\\.html\\?appid=",
  "notebook" = "/notebook/notebook\\.html\\?rid=",
  "experience" = "/experience/"
)

# Named vector of ESRI URL patterns for data services and items
esri_service_url_patterns <- c(
  "root" = "/rest/services/?$",
  "service" = paste0("(?<=/rest/services)",
                     "(", paste0(esri_service_types, collapse = "|"), ")/?$"),
  "layer" = paste0("(?<=/rest/services)",
                     "(", paste0(esri_service_types, collapse = "|"), ")",
                     "/[[:digit:]]+/?$"),
  esri_service_type_patterns
)

# Named vector of messages for what defines a valid URL of the specified type
valid_esri_url_messages <- c(
  "root" = "A {.val {type}} URL must end in {.str /rest/services}.",
  "folder" = "A {.val {type}} URL must be a 'Folder' endpoint",
  "service" = "A {.val {type}} URL must end in one of the supported service types ({esri_service_types})",
  "feature" = "A {.val {type}} URL must end in a feature ID",
  "content" = "A {.val {type}} URL must include the text {.str /content/}.",
  "search" = "A {.val {type}} URL must include the text {.str /home/search.html?q=}.",
  "item" = "An {.val {type}} URL must include the text {.str /home/item.html?id=}.",
  "group" = "A {.val {type}} URL must include the text {.str /home/group.html?id=}.",
  "user" = "A {.val {type}} URL must include the text {.str /home/user.html?user=}.",
  "scene" = "A {.val {type}} URL must include the text {.str /home/webscene/viewer.html?webscene=}.",
  "app" = "An {.val {type}} URL must include the text {.str /index.html?appid=}.",
  "notebook" = "An {.val {type}} URL must include the text {.str /notebook/notebook.html?rid=}.",
  "experience" = "An {.val {type}} URL must include the text {.str /experience/}.",
  setNames(
    paste0("A {.val {type}} URL must include the text {.str /", esri_service_types, "/} after {.str /rest/services/}"),
    esri_service_types
  )
)

# Is a character vector an ESRI service or item URL?
# @name is_esri_url
NULL
#> NULL

# - [is_esri_services_url()]: Does x match the pattern of a ESRI Item URL?
# @name is_esri_item_url
# @rdname is_esri_url
# @export
is_esri_item_url <- function(x, type = NULL) {
  is_url(
    x,
    pattern = set_url_pattern(esri_item_url_patterns, nm = type),
    perl = TRUE)
}

# - [is_esri_services_url()] Does x match the pattern of a ESRI Service URL?
# @name is_esri_services_url
# @rdname is_esri_url
# @export
is_esri_services_url <- function(x, type = NULL) {
  is_url(
    x,
    pattern = set_url_pattern(esri_service_url_patterns, nm = type),
    perl = TRUE)
}

# - [is_esri_folder_url()]: Is x a folder URL?
# @name is_esri_folder_url
# @rdname is_esri_url
# @export
is_esri_folder_url <- function(x, metadata = NULL, ..., call = caller_env()) {
  if (is.null(metadata)) {
    check_string(x, call = call)
    metadata <- fetch_layer_metadata(httr2::request(x), ..., error_call = call)
  }

  # FIXME: This is carried over from esri2sf but needs to be double-checked
  is_url(x, pattern = "/rest/services") & ("folders" %in% names(metadata))
}

check_esri_url <- function(x,
                           type = "service",
                           values = NULL,
                           allow_null = FALSE,
                           arg = caller_arg(x),
                           call = caller_env()) {
  if (allow_null && is.null(x)) {
    return(invisible(NULL))
  }

  check_url(x, arg = arg, call = call)

  if (is.null(values)) {
    values <- names(
      c(esri_item_url_patterns,
        esri_service_url_patterns,
        esri_service_type_patterns)
      )
  }

  type <- arg_match(type, values = values)

  if (type %in% names(esri_service_url_patterns)) {
    pattern <- esri_service_url_patterns
  } else if (type %in% names(esri_item_url_patterns)) {
    pattern <- esri_item_url_patterns
  } else if (type %in% names(esri_service_type_patterns)) {
    pattern <- esri_service_type_patterns
  }

  pattern <- set_url_pattern(pattern, type)

  if (is_url(x, pattern = pattern, perl = TRUE)) {
    return(invisible(NULL))
  }

  info_message <- valid_esri_url_messages[type]

  info_message <- set_names(
    info_message,
    rep_len("i", length(info_message))
  )

  cli::cli_abort(
    c("{.arg {arg}} must be a valid {.val {type}} url.",
      validation_messages),
    call = call
  )
}

# Examples

item_url <- "https://www.arcgis.com/home/item.html?id=ebeb65deb5c14f4d8849fd68944b7ee6"
search_url <- "https://www.arcgis.com/home/search.html?restrict=false&sortField=relevance&sortOrder=desc&searchTerm=census#content"
root_url <- "https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services"
server_url <- "https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/USA_Census_2020_DHC_Total_Population/FeatureServer/"
layer_url <- "https://services.arcgis.com/P3ePLMYs2RVChkJx/ArcGIS/rest/services/USA_Census_2020_DHC_Total_Population/FeatureServer/3"

is_esri_item_url(item_url)
#> [1] TRUE

is_esri_item_url(item_url, "search")
#> [1] FALSE

is_esri_item_url(search_url)
#> [1] TRUE

is_esri_item_url(search_url, "item")
#> [1] FALSE

is_esri_services_url(root_url)
#> [1] TRUE

is_esri_services_url(server_url)
#> [1] TRUE

is_esri_services_url(server_url, "root")
#> [1] FALSE

is_esri_services_url(layer_url)
#> [1] TRUE

is_esri_services_url(layer_url, "ImageServer")
#> [1] FALSE

Created on 2024-02-23 with reprex v2.1.0

Add `install` and `overwrite` parameter to `set_auth_token()` to allow token to persist across sessions

I know the ArcGIS authorization tokens expire but it is a PITA to have the set token disappear and require re-authentication every time I reset my session within R.

I have a revised, and re-revised version of the tidycensus::census_api_key() function that I've used as a token setting helper in several different packages. I'd be happy to reuse that code to implement similar features for set_auth_token(). You can see that here: https://github.com/elipousson/standaloner/blob/main/R/standalone-settoken.R

Potentially related to R-ArcGIS/arcgislayers#128

consider moving {sf} to Suggests

{sf} vendors GDAL, GEOS, and PROJ making it a massive R package. The {wk} package is very small and very lightweight and can operate on different geometry types.

It could be used instead of {sf} in many places. Where it is not possible to replace it, we can guard code execution with rlang::check_installed().

Working on {arcgisplaces}, I am thinking about how it may be used in production grade shiny applications. Since it is build mostly on Rust and httr2 it is fairly lightweight and it returns sf objects without actually having to have the package available (thank you S3 class system).

{sf} could be suggested, but shouldn't be required. Adding 300mb to a Docker container can be a limiting factor for creating a production ready application.

Add retry to arc_base_req()

It would be nice to add a retry to requests that are ran in parallel. Sometimes a feature service is overwhelmed and an error may be returned (500) but the request was fine.

The challenge though, is that the only way to find out is to parse the response which is an expensive operation and we want to do that once at most. How might that be designed?

Figure out integration testing

Changes to arcgisutils will have downstream effects on arcgislayers. It's important that these downstream changes are recognized. This will likely have to be done with revdepcheck once we get arcgislayers published.

It's important that any breaking changes are caught early

`set_auth_token()` does not accept character strings

See R-ArcGIS/arcgislayers#128

set_auth_token() is not accepting characters though it is designed to. There's a clear bug here:

function(token, quietly = FALSE) {

  stopifnot(inherits(token, c("httr2_token", "character")))

  if (inherits(token, "httr2_token")) {
    Sys.setenv("ARCGIS_TOKEN" = token[["access_token"]])
  } else if (inherits(token, "character")) {
    Sys.setenv("ARCGIS_TOKEN" = token[["access_token"]]) # FIXME: characters cannot be subset like this 
  }

  if (quietly) return(invisible())

  cat("Token set to environment variable `ARCGIS_TOKEN`")
  invisible(token)
}

There are a number of fixes that should occur here:

  • in the else if branch:
    • token should be checked to be length 1, if not, raise an error
    • token should not be subset
  • an else arm should be added with a generic error that says token cannot be set. This should be unreachable, but may be reached in some off case I can't think of.

squish_df helper

A common need from processing many requests at once is to combine the results into a single data frame. This is done ad hoc in arcgislayers and arcpbf.

arcgislayers uses do.call(rbind.data.frame) which is the slowest approach. arcpbf has adopted a hierarchy of the fastest implementations using collapse, data.table, dplyr, and base R. This should be provided in arcgisutils. It is needed in arcgeocode at the moment as well.

See R-ArcGIS/arcgislayers#167

Also: https://github.com/R-ArcGIS/arcpbf/blob/main/R/post-process.R#L109-L121

validate_crs should capture caller environment

Is your feature request related to a problem? Please describe.

validate_crs() is used to create a spatialReference json object. However this can be called many levels deep inside of a function and the context may get lost.

Describe the solution you'd like

It would be useful to introduce error_call argument to allow us to pass in the caller environment in the case that validation fails.

Additional context

Additionally validate_crs() creates a list with one element "spatialReference" in most cases we subset directly into this element making the first element superfluous. It may make sense to adjust the function to to not contain this. Note that it would require adjusting all calls to this function.

Add support for `renderer` objects and related `symbol`, `colorRamp`, and `classification` objects

Adding support for renderer objects could help support features like R-ArcGIS/arcgislayers#119 and R-ArcGIS/arcgislayers#106 from {arcgislayers}. Here are the three types of "renderers" from the developer documentation:

This will also include adding support for symbol objects:

Also color ramp objects:

And, finally, classification objects:

The documentation on drawingInfo and renderer in the Web Map Specification docs is another relevant reference.

I've put all these object types in as a checklist so I can check them off when I get them added in. If there are any existing functions for special handling of layer metadata that I should use as a model for structuring these additions, please let me know.

Error: Not a matrix - endpoint to mapserver

Describe the bug
The bug seems to be within arc_select(). Code below works fine with just running arc_open(url). Thanks.

library(arcgislayers)

url <- 'https://gisportalp.itd.idaho.gov/xserver/rest/services/RH_GeneralService/MapServer/1'

road_network <- arc_select(arc_open(url))
#> Warning: `multi_req_perform()` was deprecated in httr2 1.0.0.
#> ℹ Please use `req_perform_parallel()` instead.
#> ℹ The deprecated feature was likely used in the arcgislayers package.
#>   Please report the issue to the authors.
#> This warning is displayed once every 8 hours.
#> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
#> generated.
#> Iterating ■■ 2% | ETA: 3mIterating ■■ 4% | ETA: 2mIterating ■■■ 8% | ETA:
#> 1mIterating ■■■■ 10% | ETA: 1mIterating ■■■■ 12% | ETA: 1mIterating ■■■■■■ 15%
#> | ETA: 39sIterating ■■■■■■ 17% | ETA: 35sIterating ■■■■■■■ 19% | ETA:
#> 31sIterating ■■■■■■■■ 23% | ETA: 26sIterating ■■■■■■■■■ 25% | ETA: 24sIterating
#> ■■■■■■■■■■ 31% | ETA: 18sIterating ■■■■■■■■■■■ 33% | ETA: 20sIterating
#> ■■■■■■■■■■■ 35% | ETA: 20sIterating ■■■■■■■■■■■■■ 38% | ETA: 19sIterating
#> ■■■■■■■■■■■■■■ 42% | ETA: 17sIterating ■■■■■■■■■■■■■■ 44% | ETA: 16sIterating
#> ■■■■■■■■■■■■■■■ 46% | ETA: 15sIterating ■■■■■■■■■■■■■■■■ 50% | ETA:
#> 13sIterating ■■■■■■■■■■■■■■■■■ 52% | ETA: 12sIterating ■■■■■■■■■■■■■■■■■ 54% |
#> ETA: 12sIterating ■■■■■■■■■■■■■■■■■■ 56% | ETA: 12sIterating
#> ■■■■■■■■■■■■■■■■■■■ 60% | ETA: 10sIterating ■■■■■■■■■■■■■■■■■■■ 62% | ETA:
#> 10sIterating ■■■■■■■■■■■■■■■■■■■■■ 65% | ETA: 8sIterating ■■■■■■■■■■■■■■■■■■■■■
#> 67% | ETA: 8sIterating ■■■■■■■■■■■■■■■■■■■■■■ 69% | ETA: 7sIterating
#> ■■■■■■■■■■■■■■■■■■■■■■ 71% | ETA: 7sIterating ■■■■■■■■■■■■■■■■■■■■■■■ 73% |
#> ETA: 6sIterating ■■■■■■■■■■■■■■■■■■■■■■■ 75% | ETA: 6sIterating
#> ■■■■■■■■■■■■■■■■■■■■■■■■■ 81% | ETA: 4sIterating ■■■■■■■■■■■■■■■■■■■■■■■■■■ 83%
#> | ETA: 4sIterating ■■■■■■■■■■■■■■■■■■■■■■■■■■ 85% | ETA: 3sIterating
#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■ 87% | ETA: 3sIterating ■■■■■■■■■■■■■■■■■■■■■■■■■■■■
#> 88% | ETA: 3sIterating ■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 90% | ETA: 2sIterating
#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 92% | ETA: 2sIterating
#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 94% | ETA: 1sIterating
#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 96% | ETA: 1sIterating
#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 98% | ETA: 0s
#> Error in eval(expr, envir, enclos): Not a matrix.

Created on 2024-02-20 with reprex v2.0.2

Session info
sessioninfo::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.2.2 (2022-10-31 ucrt)
#>  os       Windows 10 x64 (build 19045)
#>  system   x86_64, mingw32
#>  ui       RTerm
#>  language (EN)
#>  collate  English_United States.utf8
#>  ctype    English_United States.utf8
#>  tz       America/Denver
#>  date     2024-02-20
#>  pandoc   3.1.1 @ C:/Program Files/RStudio/resources/app/bin/quarto/bin/tools/ (via rmarkdown)
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────
#>  package      * version date (UTC) lib source
#>  arcgislayers * 0.1.0   2023-11-13 [1] Github (R-ArcGIS/arcgislayers@67fabb2)
#>  arcgisutils    0.1.0   2023-11-14 [1] Github (R-ArcGIS/arcgisutils@bb5d292)
#>  class          7.3-22  2023-05-03 [1] CRAN (R 4.2.3)
#>  classInt       0.4-9   2023-02-28 [1] CRAN (R 4.2.3)
#>  cli            3.6.1   2023-03-23 [1] CRAN (R 4.2.3)
#>  crayon         1.5.2   2022-09-29 [1] CRAN (R 4.2.3)
#>  curl           5.2.0   2023-12-08 [1] CRAN (R 4.2.3)
#>  DBI            1.2.1   2024-01-12 [1] CRAN (R 4.2.2)
#>  digest         0.6.31  2022-12-11 [1] CRAN (R 4.2.3)
#>  dplyr          1.1.2   2023-04-20 [1] CRAN (R 4.2.3)
#>  e1071          1.7-13  2023-02-01 [1] CRAN (R 4.2.3)
#>  evaluate       0.23    2023-11-01 [1] CRAN (R 4.2.3)
#>  fansi          1.0.4   2023-01-22 [1] CRAN (R 4.2.3)
#>  fastmap        1.1.1   2023-02-24 [1] CRAN (R 4.2.3)
#>  fs             1.6.2   2023-04-25 [1] CRAN (R 4.2.3)
#>  generics       0.1.3   2022-07-05 [1] CRAN (R 4.2.3)
#>  glue           1.6.2   2022-02-24 [1] CRAN (R 4.2.3)
#>  htmltools      0.5.7   2023-11-03 [1] CRAN (R 4.2.3)
#>  httr2          1.0.0   2023-11-14 [1] CRAN (R 4.2.3)
#>  jsonify        1.2.2   2022-11-09 [1] CRAN (R 4.2.3)
#>  KernSmooth     2.23-21 2023-05-03 [1] CRAN (R 4.2.3)
#>  knitr          1.45    2023-10-30 [1] CRAN (R 4.2.3)
#>  lifecycle      1.0.4   2023-11-07 [1] CRAN (R 4.2.3)
#>  magrittr       2.0.3   2022-03-30 [1] CRAN (R 4.2.3)
#>  pillar         1.9.0   2023-03-22 [1] CRAN (R 4.2.3)
#>  pkgconfig      2.0.3   2019-09-22 [1] CRAN (R 4.2.3)
#>  proxy          0.4-27  2022-06-09 [1] CRAN (R 4.2.3)
#>  purrr          1.0.1   2023-01-10 [1] CRAN (R 4.2.3)
#>  R.cache        0.16.0  2022-07-21 [1] CRAN (R 4.2.3)
#>  R.methodsS3    1.8.2   2022-06-13 [1] CRAN (R 4.2.2)
#>  R.oo           1.25.0  2022-06-12 [1] CRAN (R 4.2.2)
#>  R.utils        2.12.2  2022-11-11 [1] CRAN (R 4.2.3)
#>  R6             2.5.1   2021-08-19 [1] CRAN (R 4.2.3)
#>  rappdirs       0.3.3   2021-01-31 [1] CRAN (R 4.2.3)
#>  Rcpp           1.0.11  2023-07-06 [1] CRAN (R 4.2.3)
#>  RcppSimdJson   0.1.10  2023-05-14 [1] CRAN (R 4.2.3)
#>  reprex         2.0.2   2022-08-17 [1] CRAN (R 4.2.3)
#>  rlang          1.1.3   2024-01-10 [1] CRAN (R 4.2.3)
#>  rmarkdown      2.25    2023-09-18 [1] CRAN (R 4.2.3)
#>  rstudioapi     0.15.0  2023-07-07 [1] CRAN (R 4.2.3)
#>  sessioninfo    1.2.2   2021-12-06 [1] CRAN (R 4.2.3)
#>  sf             1.0-14  2023-07-11 [1] CRAN (R 4.2.3)
#>  styler         1.10.1  2023-06-05 [1] CRAN (R 4.2.3)
#>  tibble         3.2.1   2023-03-20 [1] CRAN (R 4.2.3)
#>  tidyselect     1.2.0   2022-10-10 [1] CRAN (R 4.2.3)
#>  units          0.8-2   2023-04-27 [1] CRAN (R 4.2.3)
#>  utf8           1.2.3   2023-01-31 [1] CRAN (R 4.2.3)
#>  vctrs          0.6.3   2023-06-14 [1] CRAN (R 4.2.3)
#>  withr          3.0.0   2024-01-16 [1] CRAN (R 4.2.3)
#>  xfun           0.39    2023-04-20 [1] CRAN (R 4.2.3)
#>  yaml           2.3.7   2023-01-23 [1] CRAN (R 4.2.3)
#> 
#>  [1] C:/R/library
#>  [2] C:/Program Files/R/R-4.2.2/library
#> 
#> ──────────────────────────────────────────────────────────────────────────────

arc_base_req() enhancements

One of the more common causes of a failed request is an expired token. We should consider adding a check to the token to see if it has expired or not before continuing.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.