Skip to content

Commit 1adf407

Browse files
committed
Merge pull request #1078 from aronatkins/knit_params.yaml
Split yaml_params.yaml out of knit_params
2 parents f89f766 + 7a8bcc1 commit 1adf407

File tree

6 files changed

+111
-29
lines changed

6 files changed

+111
-29
lines changed

DESCRIPTION

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
Package: knitr
22
Type: Package
33
Title: A General-Purpose Package for Dynamic Report Generation in R
4-
Version: 1.10.17
4+
Version: 1.10.18
55
Date: 2015-05-06
66
Authors@R: c(
77
person("Adam", "Vogt", role = "ctb"),
88
person("Alastair", "Andrew", role = "ctb"),
99
person("Alex", "Zvoleff", role = "ctb"),
1010
person("Andre", "Simon", role = "ctb", comment = "the CSS files under inst/themes/ were derived from the Highlight package http://www.andre-simon.de"),
11+
person("Aron", "Atkins", role = "ctb"),
1112
person("Ashley", "Manton", role = "ctb"),
1213
person("Ben", "Baumer", role = "ctb"),
1314
person("Brian", "Diggs", role = "ctb"),

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export(knit_global)
5959
export(knit_hooks)
6060
export(knit_meta)
6161
export(knit_params)
62+
export(knit_params_yaml)
6263
export(knit_patterns)
6364
export(knit_print)
6465
export(knit_rd)

R/params.R

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@
77
#' the default parameter values in the R code it emits.
88
#'
99
#' @param text Character vector containing the document text
10-
#'
10+
#' @param evaluate If TRUE, expression values embedded within the YAML will be
11+
#' evaluated. This is the default. When FALSE, parameters defined by an
12+
#' expression will have the parsed expression in its \code{value} field.
13+
#'
1114
#' @return List of objects of class \code{knit_param} that correspond to the
1215
#' parameters declared in the \code{params} section of the YAML front matter.
1316
#' These objects have the following fields:
1417
#'
1518
#' \describe{
1619
#' \item{\code{name}}{The parameter name.}
1720
#' \item{\code{value}}{The default value for the parameter.}
18-
#' \item{\code{class}}{The R class names of the parameter's default value.}
1921
#' \item{\code{expr}}{The R expression (if any) that yielded the default value.}
2022
#' }
2123
#'
@@ -68,7 +70,7 @@
6870
#' }
6971
#'
7072
#' @export
71-
knit_params = function(text) {
73+
knit_params = function(text, evaluate = TRUE) {
7274

7375
# make sure each element is on one line
7476
text = split_lines(text)
@@ -78,12 +80,33 @@ knit_params = function(text) {
7880
if (is.null(yaml)) return(list())
7981

8082
yaml = enc2utf8(yaml)
83+
knit_params_yaml(yaml, evaluate = evaluate)
84+
}
85+
86+
#' Extract knit parameters from YAML text
87+
#'
88+
#' This function reads the YAML front-matter that has already been extracted
89+
#' from a document and returns a list of any parameters declared there.
90+
#'
91+
#' @param yaml Character vector containing the YAML text
92+
#' @param evaluate If TRUE, expression values embedded within the YAML will be
93+
#' evaluated. This is the default. When FALSE, parameters defined by an
94+
#' expression will have the parsed expression in its \code{value} field.
95+
#'
96+
#' @return List of objects of class \code{knit_param} that correspond to the
97+
#' parameters declared in the \code{params} section of the YAML. See
98+
#' \code{\link{knit_params}} for a full description of these objects.
99+
#'
100+
#' @seealso \code{\link{knit_params}}
101+
#'
102+
#' @export
103+
knit_params_yaml = function(yaml, evaluate = TRUE) {
81104
# parse the yaml using our handlers
82-
parsed_yaml = yaml::yaml.load(yaml, handlers = knit_params_handlers())
105+
parsed_yaml = yaml::yaml.load(yaml, handlers = knit_params_handlers(evaluate = evaluate))
83106

84107
# if we found paramters then resolve and return them
85108
if (is.list(parsed_yaml) && !is.null(parsed_yaml$params)) {
86-
resolve_params(mark_utf8(parsed_yaml$params))
109+
resolve_params(mark_utf8(parsed_yaml$params), evaluate = evaluate)
87110
} else {
88111
list()
89112
}
@@ -149,14 +172,20 @@ yaml_front_matter = function(lines) {
149172

150173

151174
# define custom handlers for knitr_params
152-
knit_params_handlers = function() {
175+
knit_params_handlers = function(evaluate = TRUE) {
153176

154177
# generic handler for r expressions where we want to preserve both the original
155178
# code and the fact that it was an expression.
156179
expr_handler = function(value) {
157-
evaluated_value = eval(parse_only(value))
158-
attr(evaluated_value, "expr") = value
159-
evaluated_value
180+
expression = parse_only(value)
181+
transformed_value = if (evaluate) {
182+
eval(expression)
183+
} else {
184+
# When we are not evaluating, provide the parsed expression as the transformed value
185+
expression
186+
}
187+
attr(transformed_value, "expr") = value
188+
transformed_value
160189
}
161190

162191
list(
@@ -189,7 +218,7 @@ knit_params_handlers = function() {
189218

190219
# resolve the raw params list into the full params data structure (with name,
191220
# type, value, and other optional fields included)
192-
resolve_params = function(params) {
221+
resolve_params = function(params, evaluate = TRUE) {
193222

194223
# get the expr attribute (if any)
195224
expr_attr = function(value) {
@@ -241,16 +270,6 @@ resolve_params = function(params) {
241270
# normalize parameter value (i.e. strip attributes, list -> vector)
242271
param$value = param_value(param$value)
243272

244-
# record parameter class (must be explicit for null values)
245-
if (!is.null(param$value)) {
246-
param$class = class(param$value)
247-
} else {
248-
if (is.null(param$class))
249-
stop("no class field specified for YAML parameter '", name, "'",
250-
" (fields with a value of null must specify an explicit class)",
251-
call. = FALSE)
252-
}
253-
254273
# add knit_param class
255274
param = structure(param, class = "knit_param")
256275

man/knit_params.Rd

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@
33
\alias{knit_params}
44
\title{Extract knit parameters from a document}
55
\usage{
6-
knit_params(text)
6+
knit_params(text, evaluate = TRUE)
77
}
88
\arguments{
99
\item{text}{Character vector containing the document text}
10+
11+
\item{evaluate}{If TRUE, expression values embedded within the YAML will be
12+
evaluated. This is the default. When FALSE, parameters defined by an
13+
expression will have the parsed expression in its \code{value} field.}
1014
}
1115
\value{
1216
List of objects of class \code{knit_param} that correspond to the
@@ -16,7 +20,6 @@ List of objects of class \code{knit_param} that correspond to the
1620
\describe{
1721
\item{\code{name}}{The parameter name.}
1822
\item{\code{value}}{The default value for the parameter.}
19-
\item{\code{class}}{The R class names of the parameter's default value.}
2023
\item{\code{expr}}{The R expression (if any) that yielded the default value.}
2124
}
2225

man/knit_params_yaml.Rd

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
% Please edit documentation in R/params.R
2+
\name{knit_params_yaml}
3+
\alias{knit_params_yaml}
4+
\title{Extract knit parameters from YAML text}
5+
\usage{
6+
knit_params_yaml(yaml, evaluate = TRUE)
7+
}
8+
\arguments{
9+
\item{yaml}{Character vector containing the YAML text}
10+
11+
\item{evaluate}{If TRUE, expression values embedded within the YAML will be
12+
evaluated. This is the default. When FALSE, parameters defined by an
13+
expression will have the parsed expression in its \code{value} field.}
14+
}
15+
\value{
16+
List of objects of class \code{knit_param} that correspond to the
17+
parameters declared in the \code{params} section of the YAML. See
18+
\code{\link{knit_params}} for a full description of these objects.
19+
}
20+
\description{
21+
This function reads the YAML front-matter that has already been extracted
22+
from a document and returns a list of any parameters declared there.
23+
}
24+
\seealso{
25+
\code{\link{knit_params}}
26+
}

tests/testit/test-params.R

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
library(testit)
22

33
# helper function to convert raw src to params list
4-
read_params <- function(src) {
4+
read_params <- function(src, evaluate = TRUE) {
55
lines <- strsplit(src, "\n")[[1]]
6-
knit_params(lines)
6+
knit_params(lines, evaluate = evaluate)
7+
}
8+
9+
# helper function to convert raw src yaml to params list
10+
read_params_yaml <- function(src, evaluate = TRUE) {
11+
knit_params_yaml(src, evaluate = evaluate)
712
}
813

914

@@ -35,10 +40,10 @@ params:
3540
'
3641
)
3742
assert(params[[1]]$name == 'start')
38-
assert('Date' %in% params[[1]]$class)
43+
assert('Date' %in% class(params[[1]]$value))
3944
assert(params[[1]]$value == as.Date("2015-01-01"))
4045
assert(params[[2]]$name == 'end')
41-
assert('POSIXct' %in% params[[2]]$class)
46+
assert('POSIXct' %in% class(params[[2]]$value))
4247
assert(params[[2]]$value == as.POSIXct("2015-01-01 12:30:00", tz = "GMT"))
4348

4449

@@ -119,13 +124,40 @@ params:
119124
'
120125
)
121126
assert(!is.null(params[[1]]$expr))
122-
assert('Date' %in% params[[1]]$class)
127+
assert('Date' %in% class(params[[1]]$value))
123128
assert(params[[2]]$expr)
124-
assert('POSIXct' %in% params[[2]]$class)
129+
assert('POSIXct' %in% class(params[[2]]$value))
125130
assert(is.null(params[[3]]$expr))
126131

132+
## test handling of unevaluated expressions --------------------------------------------
127133

134+
params <- read_params('
135+
---
136+
params:
137+
today: !r Sys.Date()
138+
---
139+
', evaluate = FALSE)
140+
assert(identical(params$today$expr, "Sys.Date()"))
141+
assert(identical(class(params$today$value), "expression"))
128142

143+
## test handling of yaml parameters --------------------------------------------
129144

145+
params <- read_params_yaml('
146+
params:
147+
x: 1
148+
today: !r Sys.Date()
149+
')
150+
assert(params$x$value == 1)
151+
assert(identical(class(params$x$value), "integer"))
152+
assert(identical(params$today$expr, "Sys.Date()"))
153+
assert('Date' %in% class(params$today$value))
130154

155+
## test handling of unevaluated yaml parameters --------------------------------------------
156+
157+
params <- read_params_yaml('
158+
params:
159+
today: !r Sys.Date()
160+
', evaluate = FALSE)
161+
assert(identical(params$today$expr, "Sys.Date()"))
162+
assert(identical(class(params$today$value), "expression"))
131163

0 commit comments

Comments
 (0)