Skip to content

Commit 6f5fb99

Browse files
committed
support for different domains, cat env vars to .Rprofile, polish and documentation
1 parent c3001b3 commit 6f5fb99

6 files changed

Lines changed: 133 additions & 61 deletions

File tree

NAMESPACE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export(get_figure)
55
export(gg2list)
66
export(ggplot_build2)
77
export(group2NA)
8-
export(knit_print.plotly_response)
8+
export(knit_print.clientresp)
99
export(layer2traces)
1010
export(paramORdefault)
1111
export(plotly)

R/plotly.R

Lines changed: 90 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
#' Create a new Plotly account.
1+
#' Create a new plotly account.
22
#'
3-
#' A sign up interface to Plotly through the R Console.
3+
#' A sign up interface to plotly through the R Console.
44
#'
5-
#' @param username Desired username
6-
#' @param email Desired email
5+
#' @param username Desired username.
6+
#' @param email Desired email.
7+
#' @param save If request is successful, should the username & API key be
8+
#' automatically stored as an environment variable in a .Rprofile?
79
#'
810
#' @return
911
#' \itemize{
@@ -12,44 +14,59 @@
1214
#' }
1315
#' @references https://plot.ly/rest/
1416
#' @export
15-
signup <- function(username, email) {
17+
signup <- function(username, email, save = TRUE) {
1618
if (missing(username)) username <- verify("username")
1719
if (missing(email)) stop("Must specify a valid email")
18-
base_url <- "https://plot.ly/apimkacct"
20+
# construct body of message to plotly server
1921
bod <- list(
2022
un = username,
2123
email = email,
2224
platform = "R",
2325
version = as.character(packageVersion("plotly"))
2426
)
27+
base_url <- file.path(get_domain(), "apimkacct")
2528
resp <- httr::POST(base_url, body = bod)
2629
stop_for_status(resp)
27-
RJSONIO::fromJSON(content(resp, as = "text"))
30+
con <- RJSONIO::fromJSON(content(resp, as = "text"))
31+
# TODO: alter the API response messages to reflect the changes in 1.0.0
32+
if (nchar(con[["error"]]) > 0) stop(con[["error"]], call. = FALSE)
33+
if (nchar(con[["message"]]) > 0) message(con[["message"]], call. = FALSE)
34+
# store API key as an environment variable in .Rprofile
35+
if (save) {
36+
cat_profile("username", con[["un"]])
37+
cat_profile("apikey", con[["api_key"]])
38+
}
39+
structure(con, class = "apimkacct")
2840
}
2941

30-
#' Main interface to plotly
42+
#' Create, modify and style plotly graphs from R
3143
#'
32-
#' Plotly interface object. See up-to-date documentation and examples at
44+
#' Create, See up-to-date documentation and examples at
3345
#' https://plot.ly/API
3446
#'
3547
#' @param p Either a ggplot object or a list of data/arguments to post to the
36-
#' plotly api.
48+
#' plotly API.
3749
#' @param browse should the default web browser be prompted to open the Plotly result?
38-
#' @param ... additional arguments passed onto \code{plotly_POST}.
39-
#' @references https://plot.ly/API
50+
#' @param ... additional arguments passed onto \link{plotly_POST}.
51+
#' @seealso \link{signup}, \link{plotly_POST}
4052
#' @import httr RJSONIO
4153
#' @export
4254
#' @examples \dontrun{
43-
#' # You need a plotly username and API key to communicate with
44-
#' # the plotly API. These are accessed via environment variables.
55+
#' # You need a plotly username and API key to communicate with the plotly API.
56+
#'
4557
#' # If you don't already have an API key, you can obtain one with a valid
46-
#' # username and email via the signup() function.
47-
#' usr <- 'anna.lyst'
48-
#' Sys.setenv(`plotly-username` = usr)
49-
#' resp <- signup(usr, 'anna.lyst@@plot.ly')
50-
#' Sys.setenv(`plotly-apikey` = resp[["apikey"]])
51-
#' # Note that you can set environment variables in your .Rprofile if you
52-
#' # don't want to set them everytime you start R.
58+
#' # username and email via signup().
59+
#' s <- signup('anna.lyst', 'anna.lyst@@plot.ly')
60+
#'
61+
#' # If you already have a username and API key, please create the following
62+
#' # environment variables:
63+
#' Sys.setenv(`plotly-username` = "me")
64+
#' Sys.setenv(`plotly-apikey` = "mykey")
65+
#' # You can also change the default domain if you have a plotly server.
66+
#' Sys.setenv(`plotly-domain` = "http://mydomain.com")
67+
#'
68+
#' # If you don't want to specify these environment variables everytime you
69+
#' # start R, you can put that code in a .Rprofile (see help(.Rprofile))
5370
#'
5471
#' # Send data directly to Plotly's Javascript Graphing Library
5572
#' # https://plot.ly/javascript-graphing-library/
@@ -76,26 +93,44 @@ plotly <- function(p = last_plot(), browse = interactive(), ...) {
7693
} else if (!is.list(p)) {
7794
stop("p must be either a ggplot object or a list")
7895
}
79-
# how to best map list to a post message?
96+
# In an effort to save some legacy users headache...
97+
# specifying username and key should still work
98+
.args <- as.list(match.call())
99+
if ("username" %in% names(.args))
100+
Sys.setenv(`plotly-username` = args[["username"]])
101+
if ("key" %in% names(.args))
102+
Sys.setenv(`plotly-apikey` = args[["key"]])
103+
if (!"data" %in% names(p))
104+
stop("p should have at least one element named 'data'",
105+
"(which is mapped to the args parameter in the plotly REST API).")
80106
resp <- plotly_POST(p$data, list(layout = p$layout), ...)
81107
if (browse) browseURL(resp[["url"]])
82108
resp
83109
}
84110

85-
#' POST messages to plotly's REST API
111+
#' Create, modify and style plotly graphs from R
112+
#'
113+
#' POST messages to the clientresp resource of plotly's REST API. Unlike \link{plotly},
114+
#' this function does not support ggplot objects.
115+
#'
86116
#' @param args a list. For details see the rest API docs.
87117
#' @param kwargs a list. For details see the rest API docs.
88118
#' @param origin a character vector of length one. For details see the rest API docs.
89119
#' @param ... arguments passed along to \code{httr::POST()}
90120
#' @export
91121
#' @references https://plot.ly/rest/
122+
#' @seealso \link{signup}, \link{plotly}
92123
#' @return An R object created by mapping the JSON content of the plotly API
93-
#' response to its R equivalent. This object has a class of "plotly_response"
124+
#' response to its R equivalent. This object has a class of "clientresp"
94125
#' @examples
95126
#'
96127
#' args <- list(c(0, 1, 2), c(3, 4, 5), c(1, 2, 3), c(6, 6, 5))
97128
#' resp <- plotly_POST(args)
98129
#'
130+
#' # translate a ggplot object with gg2list(), then upload to plotly
131+
#' p <- gg2list(qplot(1:10))
132+
#' resp <- plotly_POST(p$data, list(layout = p$layout), ...)
133+
#'
99134
plotly_POST <- function(args, kwargs = list(filename = "plot from api", fileopt = "new"),
100135
origin = "plot", ...) {
101136
# some basic input checks
@@ -111,18 +146,18 @@ plotly_POST <- function(args, kwargs = list(filename = "plot from api", fileopt
111146
key = verify("apikey"),
112147
origin = origin,
113148
platform = "R",
114-
version = "0.5.20",
149+
version = as.character(packageVersion("plotly")),
115150
args = RJSONIO::toJSON(args, digits = 50, collapse = ""),
116151
kwargs = RJSONIO::toJSON(kwargs, digits = 50, collapse = "")
117152
)
118-
# TODO: support different plotly domains?
119-
resp <- httr::POST("https://plot.ly/clientresp", body = bod, ...)
153+
base_url <- file.path(get_domain(), "clientresp")
154+
resp <- httr::POST(base_url, body = bod, ...)
120155
stop_for_status(resp)
121-
cont <- RJSONIO::fromJSON(content(resp, as = "text"))
122-
if (nchar(cont[["error"]]) > 0) stop(cont[["error"]], call. = FALSE)
123-
if (nchar(cont[["warning"]]) > 0) warning(cont[["warning"]], call. = FALSE)
124-
if (nchar(cont[["message"]]) > 0) message(cont[["message"]], call. = FALSE)
125-
structure(cont, class = "plotly_response")
156+
con <- RJSONIO::fromJSON(content(resp, as = "text"))
157+
if (nchar(con[["error"]]) > 0) stop(con[["error"]], call. = FALSE)
158+
if (nchar(con[["warning"]]) > 0) warning(con[["warning"]], call. = FALSE)
159+
if (nchar(con[["message"]]) > 0) message(con[["message"]], call. = FALSE)
160+
structure(con, class = "clientresp")
126161
}
127162

128163
#' Request data/layout for a particular Plotly figure
@@ -149,7 +184,7 @@ get_figure <- function(username, id) {
149184
#' @param ... placeholder.
150185
#' @export
151186
#' @references https://github.com/yihui/knitr/blob/master/vignettes/knit_print.Rmd
152-
knit_print.plotly_response <- function(x, options, ...) {
187+
knit_print.clientresp <- function(x, options, ...) {
153188
if (!requireNamespace("knitr")) {
154189
warning("Please install.packages('knitr')")
155190
return(x)
@@ -166,7 +201,7 @@ knit_print.plotly_response <- function(x, options, ...) {
166201
#' @param height attribute of the iframe
167202
#' @export
168203
embed_notebook <- function(url, width = "100%", height = "525") {
169-
if (!inherits(p, "plotly_response")) {
204+
if (!inherits(p, "clientresp")) {
170205
p <- plotly(p)
171206
url <- p[["url"]]
172207
}
@@ -182,6 +217,10 @@ embed_notebook <- function(url, width = "100%", height = "525") {
182217
# Non-exported helper functions
183218
# ----------------------------------------
184219

220+
get_domain <- function() {
221+
Sys.getenv("plotly-domain", "https://plot.ly")
222+
}
223+
185224
plotly_headers <- function() {
186225
httr::add_headers(.headers = c(
187226
"plotly-username" = verify("username"),
@@ -203,6 +242,23 @@ plotly_iframe <- function(url, width, height) {
203242
url, "\" width=\"", width, "\" frameBorder=\"0\"></iframe>", sep="")
204243
}
205244

245+
# try to write environment variables to an .Rprofile
246+
cat_profile <- function(key, value, path = "~") {
247+
r_profile <- file.path(normalizePath(path, mustWork = TRUE),
248+
".Rprofile")
249+
snippet <- sprintf('\nSys.setenv(`plotly-%s` = "%s")', key, value)
250+
if (!file.exists(r_profile)) {
251+
message("Creating", r_profile)
252+
r_profile_con <- file(r_profile)
253+
}
254+
if (file.access(r_profile, 2) != 0)
255+
stop("R doesn't have permission to write to this file: ", path)
256+
if (file.access(r_profile, 4) != 0)
257+
stop("R doesn't have permission to read this file: ", path)
258+
message("Adding plotly-", key, " environment variable to ", r_profile)
259+
cat(snippet, file = r_profile, append = TRUE)
260+
}
261+
206262
# bummer, looks like we can't use RStudio's viewer (yet) --
207263
# https://github.com/rstudio/rstudioapi/issues/2#issuecomment-99250180
208264
# browse_url <- function(url) {
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
% Generated by roxygen2 (4.1.1): do not edit by hand
22
% Please edit documentation in R/plotly.R
3-
\name{knit_print.plotly_response}
4-
\alias{knit_print.plotly_response}
3+
\name{knit_print.clientresp}
4+
\alias{knit_print.clientresp}
55
\title{Embed a plotly iframe into an R markdown document via \code{knit_print}}
66
\usage{
7-
knit_print.plotly_response(x, options, ...)
7+
knit_print.clientresp(x, options, ...)
88
}
99
\arguments{
1010
\item{x}{named list of ggplots and option lists to pass to \code{animint2dir}.}

man/plotly.Rd

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,39 @@
22
% Please edit documentation in R/plotly.R
33
\name{plotly}
44
\alias{plotly}
5-
\title{Main interface to plotly}
5+
\title{Create, modify and style plotly graphs from R}
66
\usage{
77
plotly(p = last_plot(), browse = interactive(), ...)
88
}
99
\arguments{
1010
\item{p}{Either a ggplot object or a list of data/arguments to post to the
11-
plotly api.}
11+
plotly API.}
1212

1313
\item{browse}{should the default web browser be prompted to open the Plotly result?}
1414

15-
\item{...}{additional arguments passed onto \code{plotly_POST}.}
15+
\item{...}{additional arguments passed onto \link{plotly_POST}.}
1616
}
1717
\description{
18-
Plotly interface object. See up-to-date documentation and examples at
18+
Create, See up-to-date documentation and examples at
1919
https://plot.ly/API
2020
}
2121
\examples{
2222
\dontrun{
23-
# You need a plotly username and API key to communicate with
24-
# the plotly API. These are accessed via environment variables.
23+
# You need a plotly username and API key to communicate with the plotly API.
24+
2525
# If you don't already have an API key, you can obtain one with a valid
26-
# username and email via the signup() function.
27-
usr <- 'anna.lyst'
28-
Sys.setenv(`plotly-username` = usr)
29-
resp <- signup(usr, '[email protected]')
30-
Sys.setenv(`plotly-apikey` = resp[["apikey"]])
31-
# Note that you can set environment variables in your .Rprofile if you
32-
# don't want to set them everytime you start R.
26+
# username and email via signup().
27+
s <- signup('anna.lyst', '[email protected]')
28+
29+
# If you already have a username and API key, please create the following
30+
# environment variables:
31+
Sys.setenv(`plotly-username` = "me")
32+
Sys.setenv(`plotly-apikey` = "mykey")
33+
# You can also change the default domain if you have a plotly server.
34+
Sys.setenv(`plotly-domain` = "http://mydomain.com")
35+
36+
# If you don't want to specify these environment variables everytime you
37+
# start R, you can put that code in a .Rprofile (see help(.Rprofile))
3338

3439
# Send data directly to Plotly's Javascript Graphing Library
3540
# https://plot.ly/javascript-graphing-library/
@@ -51,7 +56,7 @@ viz <- ggplot(canada.cities, aes(long, lat)) +
5156
plotly(viz)
5257
}
5358
}
54-
\references{
55-
https://plot.ly/API
59+
\seealso{
60+
\link{signup}, \link{plotly_POST}
5661
}
5762

man/plotly_POST.Rd

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
% Please edit documentation in R/plotly.R
33
\name{plotly_POST}
44
\alias{plotly_POST}
5-
\title{POST messages to plotly's REST API}
5+
\title{Create, modify and style plotly graphs from R}
66
\usage{
77
plotly_POST(args, kwargs = list(filename = "plot from api", fileopt = "new"),
88
origin = "plot", ...)
@@ -18,16 +18,24 @@ plotly_POST(args, kwargs = list(filename = "plot from api", fileopt = "new"),
1818
}
1919
\value{
2020
An R object created by mapping the JSON content of the plotly API
21-
response to its R equivalent. This object has a class of "plotly_response"
21+
response to its R equivalent. This object has a class of "clientresp"
2222
}
2323
\description{
24-
POST messages to plotly's REST API
24+
POST messages to the clientresp resource of plotly's REST API. Unlike \link{plotly},
25+
this function does not support ggplot objects.
2526
}
2627
\examples{
2728
args <- list(c(0, 1, 2), c(3, 4, 5), c(1, 2, 3), c(6, 6, 5))
2829
resp <- plotly_POST(args)
30+
31+
# translate a ggplot object with gg2list(), then upload to plotly
32+
p <- gg2list(qplot(1:10))
33+
resp <- plotly_POST(p$data, list(layout = p$layout), ...)
2934
}
3035
\references{
3136
https://plot.ly/rest/
3237
}
38+
\seealso{
39+
\link{signup}, \link{plotly}
40+
}
3341

man/signup.Rd

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22
% Please edit documentation in R/plotly.R
33
\name{signup}
44
\alias{signup}
5-
\title{Create a new Plotly account.}
5+
\title{Create a new plotly account.}
66
\usage{
7-
signup(username, email)
7+
signup(username, email, save = TRUE)
88
}
99
\arguments{
10-
\item{username}{Desired username}
10+
\item{username}{Desired username.}
1111

12-
\item{email}{Desired email}
12+
\item{email}{Desired email.}
13+
14+
\item{save}{If request is successful, should the username & API key be
15+
automatically stored as an environment variable in a .Rprofile?}
1316
}
1417
\value{
1518
\itemize{
@@ -18,7 +21,7 @@ signup(username, email)
1821
}
1922
}
2023
\description{
21-
A sign up interface to Plotly through the R Console.
24+
A sign up interface to plotly through the R Console.
2225
}
2326
\references{
2427
https://plot.ly/rest/

0 commit comments

Comments
 (0)