Skip to content

Commit

Permalink
Dash for R v0.3.0 (#175)
Browse files Browse the repository at this point in the history
* Autoset routes and requests pathname prefixes (#165)

* Inspect environment variables for host & port (#167)

* Support for index page templating (#168)

* Add support for config-aware relative paths (#172)

* Add unit tests for index customization (#176)

* Send status code of 1 when unit tests fail (#177)
  • Loading branch information
rpkyle authored Feb 13, 2020
1 parent f81fcb5 commit f6a2172
Show file tree
Hide file tree
Showing 9 changed files with 484 additions and 55 deletions.
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
. venv/bin/activate
pip install -e git+https://github.com/plotly/dash.git#egg=dash[testing]
export PATH=$PATH:/home/circleci/.local/bin/
pytest --log-cli-level DEBUG --nopercyfinalize --junitxml=test-reports/dashr.xml tests/integration/
pytest --nopercyfinalize --junitxml=test-reports/dashr.xml tests/integration/
- store_artifacts:
path: test-reports
- store_test_results:
Expand All @@ -55,7 +55,7 @@ jobs:
- run:
name: 🔎 Unit tests
command: |
sudo Rscript -e 'testthat::test_dir("tests/")'
sudo Rscript -e 'res=devtools::test("tests/", reporter=default_reporter());df=as.data.frame(res);if(sum(df$failed) > 0 || any(df$error)) {q(status=1)}'
workflows:
version: 2
Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
# Change Log for Dash for R
All notable changes to this project will be documented in this file.


## [0.3.0] - 2020-02-12
### Added
- Support for config-aware relative paths [#172](https://github.com/plotly/dashR/pull/172)
- Support index customization and index templates [#168](https://github.com/plotly/dashR/pull/168)
- Application titles may be set using the `app$title()` method, for parity with Dash for Python's `app.title` syntax [#168](https://github.com/plotly/dashR/pull/168)

### Changed
- Dash for R now requires `dashCoreComponents` v1.8.0
- Dash for R now requires `dashTable` v4.6.0
- Automatically set routes and requests pathname prefixes if `DASH_APP_NAME` environment variable has been set [#165](https://github.com/plotly/dashR/pull/165)

### Deprecated
- Application titles can no longer be set using `name` parameter, which is now deprecated with a warning, for parity with Dash for Python [#168](https://github.com/plotly/dashR/pull/168)
- Removed `DASH_HOST` and `DASH_PORT`, Dash for R now respects `HOST` and `PORT` [#167](https://github.com/plotly/dashR/pull/167)

## [0.2.0] - 2020-01-03
### Added
- Support for asynchronous/dynamic loading of dependencies, resource caching, and asset fingerprinting [#157](https://github.com/plotly/dashR/pull/157)
Expand Down Expand Up @@ -28,6 +44,7 @@ All notable changes to this project will be documented in this file.
- Fixes for hot reloading interval handling and refreshing apps within viewer pane [#148](https://github.com/plotly/dashR/pull/148)
- `get_asset_url` checks `getAppPath()` as well as `DASH_APP_ROOT_PATH` environment variable when invoked [#161](https://github.com/plotly/dashR/pull/161)


## [0.1.0] - 2019-07-10
### Added
- Initial release
Expand Down
12 changes: 6 additions & 6 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
Package: dash
Title: An Interface to the Dash Ecosystem for Authoring Reactive Web Applications
Version: 0.2.0
Authors@R: c(person("Chris", "Parmer", role = c("aut"), email = "chris@plot.ly"), person("Ryan Patrick", "Kyle", role = c("aut", "cre"), comment = c(ORCID = "0000-0001-5829-9867"), email = "ryan@plot.ly"), person("Carson", "Sievert", role = c("aut"), comment = c(ORCID = "0000-0002-4958-2844")), person(family = "Plotly Technologies", role = "cph"))
Version: 0.3.0
Authors@R: c(person("Chris", "Parmer", role = c("aut"), email = "chris@plot.ly"), person("Ryan Patrick", "Kyle", role = c("aut", "cre"), comment = c(ORCID = "0000-0001-5829-9867"), email = "ryan@plot.ly"), person("Carson", "Sievert", role = c("aut"), comment = c(ORCID = "0000-0002-4958-2844")), person("Hammad", "Khan", role = c("aut"), email = "hammadkhan@plot.ly"), person(family = "Plotly Technologies", role = "cph"))
Description: A framework for building analytical web applications, Dash offers a pleasant and productive development experience. No JavaScript required.
Depends:
R (>= 3.0.2)
Imports:
dashHtmlComponents (== 1.0.2),
dashCoreComponents (== 1.6.0),
dashTable (== 4.5.1),
dashCoreComponents (== 1.8.0),
dashTable (== 4.6.0),
R6,
fiery (> 1.0.0),
routr (> 0.2.0),
Expand All @@ -32,8 +32,8 @@ Collate:
'print.R'
'internal.R'
Remotes: plotly/dash-html-components@55c3884,
plotly/dash-core-components@c107e0f,
plotly/dash-table@3058bd5
plotly/dash-core-components@fc153b4,
plotly/dash-table@79d46ca
License: MIT + file LICENSE
Encoding: UTF-8
LazyData: true
Expand Down
236 changes: 203 additions & 33 deletions R/dash.R

Large diffs are not rendered by default.

93 changes: 84 additions & 9 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -457,22 +457,25 @@ valid_seq <- function(params) {
}
}

resolve_prefix <- function(prefix, environment_var, base_pathname) {
resolvePrefix <- function(prefix, environment_var, base_pathname) {
if (!(is.null(prefix))) {
assertthat::assert_that(is.character(prefix))

return(prefix)
} else {
# Check environment variables
prefix_env <- Sys.getenv(environment_var)
if (prefix_env != "") {
env_base_pathname <- Sys.getenv("DASH_URL_BASE_PATHNAME")
app_name <- Sys.getenv("DASH_APP_NAME")

if (prefix_env != "")
return(prefix_env)
} else {
env_base_pathname <- Sys.getenv("DASH_URL_BASE_PATHNAME")
if (env_base_pathname != "")
return(env_base_pathname)
else
return(base_pathname)
}
else if (app_name != "")
return(sprintf("/%s/", app_name))
else if (env_base_pathname != "")
return(env_base_pathname)
else
return(base_pathname)
}
}

Expand Down Expand Up @@ -1267,3 +1270,75 @@ tryCompress <- function(request, response) {
}
return(response$compress())
}

get_relative_path <- function(requests_pathname, path) {
# Returns a path with the config setting 'requests_pathname_prefix' prefixed to
# it. This is particularly useful for apps deployed on Dash Enterprise, which makes
# it easier to serve apps under both URL prefixes and localhost.

if (requests_pathname == "/" && path == "") {
return("/")
}
else if (requests_pathname != "/" && path == "") {
return(requests_pathname)
}
else if (!startsWith(path, "/")) {
stop(sprintf(paste0("Unsupported relative path! Paths that aren't prefixed" ,
"with a leading '/' are not supported. You supplied '%s'."),
path))
}
else {
return(paste(gsub("/$", "", requests_pathname), gsub("^/", "", path), sep = "/"))
}
}

strip_relative_path <- function(requests_pathname, path) {
# Returns a relative path with the `requests_pathname_prefix` and leadings and trailing
# slashes stripped from it. This function is particularly relevant to dccLocation pathname routing.

if (is.null(path)) {
return(NULL)
}
else if ((requests_pathname != "/" && !startsWith(path, gsub("/$", "", requests_pathname)))
|| (requests_pathname == "/" && !startsWith(path, "/"))) {
stop(sprintf(paste0("Unsupported relative path! Path's that are not prefixed ",
"with a leading 'requests_pathname_prefix` are not suported. ",
"You supplied '%s', and requests_pathname_prefix was '%s'."),
path, requests_pathname
))
}
else if (requests_pathname != "/" && startsWith(path, gsub("/$", "", requests_pathname))) {
path = sub(gsub("/$", "", requests_pathname), "", path)
}
return(trimws(gsub("/", "", path)))
}

interpolate_str <- function(index_template, ...) {
# This function takes an index string, along with
# user specified keys for the html keys of the index
# and sets the default values of the keys to the
# ones specified by the keys themselves, returning
# the custom index template.
template = index_template
kwargs <- list(...)

for (name in names(kwargs)) {
key = paste0('\\{', name, '\\}')

template = sub(key, kwargs[[name]], template)
}
return(template)
}

validate_keys <- function(string) {
required_keys <- c("app_entry", "config", "scripts")

keys_present <- vapply(required_keys, function(x) grepl(x, string), logical(1))

if (!all(keys_present)) {
stop(sprintf("Did you forget to include %s in your index string?",
paste(names(keys_present[keys_present==FALSE]), collapse = ", ")))
} else {
return(string)
}
}
69 changes: 64 additions & 5 deletions man/Dash.Rd

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

1 change: 1 addition & 0 deletions man/dash-package.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Authors:
\item Chris Parmer \email{chris@plot.ly}
\item Ryan Patrick Kyle \email{ryan@plot.ly}
\item Carson Sievert
\item Hammad Khan \email{hammadkhan@plot.ly}
}

Other contributors:
Expand Down
55 changes: 55 additions & 0 deletions tests/integration/test_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
named_app = """
library(dash)
library(dashHtmlComponents)
app <- Dash$new()
app$title("Testing")
app$layout(htmlDiv(list(htmlDiv(id='container',children='Hello Dash for R testing'))))
app$run_server()
"""

app_with_template = """
library(dash)
library(dashHtmlComponents)
app <- Dash$new()
string <-
"<!DOCTYPE html>
<html>
<head>
{%meta_tags%}
<title>Testing Again</title>
{%favicon%}
{%css_tags%}
</head>
<body>
{%app_entry%}
<footer>
{%config%}
{%scripts%}
</footer>
</body>
</html>"
app$index_string(string)
app$layout(htmlDiv(list(htmlDiv(id='container',children='Hello Dash for R testing'))))
app$run_server()
"""


def test_rapp001r_with_appname(dashr):
dashr.start_server(named_app)
dashr.wait_for_text_to_equal(
"#container", "Hello Dash for R testing", timeout=1
)
assert dashr.find_element("title").get_attribute("text") == "Testing"


def test_rapp002_r_with_template(dashr):
dashr.start_server(app_with_template)
dashr.wait_for_text_to_equal(
"#container", "Hello Dash for R testing", timeout=1
)
assert dashr.find_element("title").get_attribute("text") == "Testing Again"
Loading

0 comments on commit f6a2172

Please sign in to comment.