Skip to content

Commit 4dde500

Browse files
authored
Merge pull request #1184 from RcppCore/pr/1183
Adding Rcpp signature attribute
2 parents b883b03 + 2f4280a commit 4dde500

File tree

9 files changed

+420
-20
lines changed

9 files changed

+420
-20
lines changed

.codecov.yml

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
1-
comment:
2-
layout: "header, diff, tree, changes"
3-
behavior: default
4-
require_changes: false # if true: only post the comment if coverage changes
5-
branches: null
6-
flags: null
7-
paths: null
1+
comment: false
2+
coverage:
3+
status:
4+
project:
5+
default:
6+
target: 70% # the (on purpose low) required coverage value
7+
threshold: 2% # the permitted delta in hitting the target
8+
patch:
9+
default:
10+
target: 0% # the (on purpose low) required coverage value
11+
12+
# layout: "header, diff, tree, changes"
13+
# behavior: default
14+
# require_changes: false # if true: only post the comment if coverage changes
15+
# branches: null
16+
# flags: null
17+
# paths: null

ChangeLog

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,26 @@
1+
2021-10-15 Travers Ching <traversc@gmail.com>
2+
3+
* inst/tinytest/testRcppAttributePackage: Tests `signature` attribute
4+
* inst/tinytest/test_attribute_package.R: Tests `signature` attribute
5+
16
2021-10-13 Dirk Eddelbuettel <edd@debian.org>
27

38
* README.md: Switch JSS url to doi form per JSS request
49
* man/Rcpp-package.Rd: Idem
510
* man/RcppLdFlags.Rd: Idem
611
* inst/CITATION: Only use doi entries in three citEntry blocks
712

13+
2021-10-11 Dirk Eddelbuettel <edd@debian.org>
14+
15+
* DESCRIPTION (Version, Date): Roll minor version
16+
* inst/include/Rcpp/config.h: Idem
17+
18+
* .codecov.yml (comment): Disable codecov comments on PRs
19+
20+
2021-10-10 Travers Ching <traversc@gmail.com>
21+
22+
* src/attributes.cpp: Add `signature` attribute and syntax checks
23+
824
2021-10-02 Dirk Eddelbuettel <edd@debian.org>
925

1026
* .github/workflows/docker.yaml (jobs): Add container builder action

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: Rcpp
22
Title: Seamless R and C++ Integration
3-
Version: 1.0.7.3
3+
Version: 1.0.7.4
44
Date: 2021-10-01
55
Author: Dirk Eddelbuettel, Romain Francois, JJ Allaire, Kevin Ushey, Qiang Kou,
66
Nathan Russell, Inaki Ucar, Douglas Bates and John Chambers

inst/include/Rcpp/config.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
#define RCPP_VERSION_STRING "1.0.7"
3131

3232
// the current source snapshot (using four components, if a fifth is used in DESCRIPTION we ignore it)
33-
#define RCPP_DEV_VERSION RcppDevVersion(1,0,7,3)
34-
#define RCPP_DEV_VERSION_STRING "1.0.7.3"
33+
#define RCPP_DEV_VERSION RcppDevVersion(1,0,7,4)
34+
#define RCPP_DEV_VERSION_STRING "1.0.7.4"
3535

3636
#endif
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Package: testRcppAttributePackage
2+
Type: Package
3+
Title: Tests the signature attribute and other attributes in package compilation
4+
Version: 1.0
5+
Date: 2021-10-09
6+
Author: Travers Ching
7+
Maintainer: Dirk Eddelbuettel <edd@debian.org>
8+
Description: Small test package part of Rcpp unit tests
9+
License: GPL (>= 2)
10+
Imports: Rcpp (>= 1.0.7)
11+
LinkingTo: Rcpp
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
useDynLib(testRcppAttributePackage, .registration=TRUE)
2+
importFrom(Rcpp, evalCpp)
3+
exportPattern("^[[:alpha:]]+")
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#include <Rcpp.h>
2+
using namespace Rcpp;
3+
4+
// [[Rcpp::interfaces(r, cpp)]]
5+
6+
// [[Rcpp::export]]
7+
List test_no_attributes(List x, bool verbose) {
8+
if(x.size() > 0) {
9+
CharacterVector first_element = x[0];
10+
return List::create(first_element, verbose);
11+
} else {
12+
return List::create(verbose);
13+
}
14+
}
15+
16+
// [[Rcpp::export( signature = {x = list("{A}", "B"), verbose = getOption("verbose")} )]]
17+
List test_signature(List x, bool verbose) {
18+
if(x.size() > 0) {
19+
CharacterVector first_element = x[0];
20+
return List::create(first_element, verbose);
21+
} else {
22+
return List::create(verbose);
23+
}
24+
}
25+
26+
// [[Rcpp::export( rng = false, signature = {x = list("{A}", "B"), verbose = getOption("verbose")}, invisible = true )]]
27+
List test_rng_false_signature_invisible_true(List x, bool verbose) {
28+
if(x.size() > 0) {
29+
CharacterVector first_element = x[0];
30+
return List::create(first_element, verbose);
31+
} else {
32+
return List::create(verbose);
33+
}
34+
}
35+
36+
// [[Rcpp::export( rng = false )]]
37+
List test_rng_false(List x, bool verbose) {
38+
if(x.size() > 0) {
39+
CharacterVector first_element = x[0];
40+
return List::create(first_element, verbose);
41+
} else {
42+
return List::create(verbose);
43+
}
44+
}
45+
46+
// [[Rcpp::export( rng = true )]]
47+
List test_rng_true(List x, bool verbose) {
48+
if(x.size() > 0) {
49+
CharacterVector first_element = x[0];
50+
return List::create(first_element, verbose);
51+
} else {
52+
return List::create(verbose);
53+
}
54+
}
55+
56+
// [[Rcpp::export( signature = {x = list("{A}", "B"), verbose = getOption("verbose")}, rng = true )]]
57+
List test_rng_true_signature(List x, bool verbose) {
58+
if(x.size() > 0) {
59+
CharacterVector first_element = x[0];
60+
return List::create(first_element, verbose);
61+
} else {
62+
return List::create(verbose);
63+
}
64+
}
65+
66+
67+
// [[Rcpp::export( invisible = true, rng = true )]]
68+
List test_invisible_true_rng_true(List x, bool verbose) {
69+
if(x.size() > 0) {
70+
CharacterVector first_element = x[0];
71+
return List::create(first_element, verbose);
72+
} else {
73+
return List::create(verbose);
74+
}
75+
}
76+
77+
// [[Rcpp::export( invisible = true )]]
78+
List test_invisible_true(List x, bool verbose) {
79+
if(x.size() > 0) {
80+
CharacterVector first_element = x[0];
81+
return List::create(first_element, verbose);
82+
} else {
83+
return List::create(verbose);
84+
}
85+
}
86+
87+
// [[Rcpp::export( invisible = true, signature = {x = list("{A}", "B"), verbose = getOption("verbose")} )]]
88+
List test_invisible_true_signature(List x, bool verbose) {
89+
if(x.size() > 0) {
90+
CharacterVector first_element = x[0];
91+
return List::create(first_element, verbose);
92+
} else {
93+
return List::create(verbose);
94+
}
95+
}
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
## Copyright (C) 2010 - 2020 Dirk Eddelbuettel and Romain Francois
2+
## Copyright (C) 2021 Dirk Eddelbuettel, Romain Francois and Travers Ching
3+
##
4+
## This file is part of Rcpp.
5+
##
6+
## Rcpp is free software: you can redistribute it and/or modify it
7+
## under the terms of the GNU General Public License as published by
8+
## the Free Software Foundation, either version 2 of the License, or
9+
## (at your option) any later version.
10+
##
11+
## Rcpp is distributed in the hope that it will be useful, but
12+
## WITHOUT ANY WARRANTY; without even the implied warranty of
13+
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
## GNU General Public License for more details.
15+
##
16+
## You should have received a copy of the GNU General Public License
17+
## along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
18+
19+
.runThisTest <- Sys.getenv("RunAllRcppTests") == "yes" && Sys.getenv("RunVerboseRcppTests") == "yes"
20+
21+
if (! .runThisTest) exit_file("Set 'RunVerboseRcppTests' and 'RunAllRcppTests' to 'yes' to run.")
22+
23+
td <- tempfile()
24+
cwd <- getwd()
25+
dir.create(td)
26+
pkg <- "testRcppAttributePackage"
27+
file.copy(pkg, td, recursive = TRUE) # simpler direct path thanks to tinytest
28+
setwd(td)
29+
on.exit( { setwd(cwd); unlink(td, recursive = TRUE) } )
30+
R <- shQuote(file.path( R.home(component = "bin"), "R"))
31+
Rcpp::compileAttributes(pkg)
32+
cmd <- paste(R, "CMD build", pkg)
33+
invisible(system(cmd, intern=TRUE))
34+
dir.create("templib")
35+
pkgfile <- paste0(pkg, "_1.0.tar.gz")
36+
install.packages(pkgfile, "templib", repos = NULL, type = "source")
37+
require(pkg, lib.loc = "templib", character.only = TRUE)
38+
39+
# Test Package
40+
options(verbose=TRUE)
41+
expect_equal(test_no_attributes(list("{A}"), FALSE),list("{A}", FALSE))
42+
expect_equal(test_signature(),list("{A}", TRUE))
43+
expect_equal(test_rng_false_signature_invisible_true(),list("{A}", TRUE))
44+
expect_equal(test_rng_false(list("{A}"), FALSE),list("{A}", FALSE))
45+
expect_equal(test_rng_true(list("{A}"), FALSE),list("{A}", FALSE))
46+
expect_equal(test_rng_true_signature(),list("{A}", TRUE))
47+
expect_equal(test_invisible_true_rng_true(list("{A}"), FALSE),list("{A}", FALSE))
48+
expect_equal(test_invisible_true(list("{A}"), FALSE),list("{A}", FALSE))
49+
expect_equal(test_invisible_true_signature(),list("{A}", TRUE))
50+
options(verbose=FALSE)
51+
52+
# Test inline
53+
54+
# test 0
55+
# This example should just run and not crash
56+
Rcpp::sourceCpp(code='
57+
#include <Rcpp.h>
58+
using namespace Rcpp;
59+
// [[Rcpp::export( rng = false, signature = {x=list("{A}", "B"), verbose = getOption("verbose")}, invisible = TRUE )]]
60+
List test_inline(List x, bool verbose) {
61+
if(x.size() > 0) {
62+
CharacterVector first_element = x[0];
63+
return List::create(first_element, verbose);
64+
} else {
65+
return List::create(verbose);
66+
}
67+
}')
68+
expect_equal(test_inline(), list("{A}", FALSE))
69+
options(verbose=TRUE)
70+
expect_equal(test_inline(), list("{A}", TRUE))
71+
options(verbose=FALSE)
72+
73+
# test 1, from Enchufa2
74+
# The verbose argument should be replaced with FALSE
75+
Rcpp::sourceCpp(code='
76+
#include <Rcpp.h>
77+
using namespace Rcpp;
78+
// [[Rcpp::export( rng = false, signature = {x=list("{A}", "B"), verbose=FALSE} )]]
79+
List test_inline(List x, bool verbose=true) {
80+
if(x.size() > 0) {
81+
CharacterVector first_element = x[0];
82+
return List::create(first_element, verbose);
83+
} else {
84+
return List::create(verbose);
85+
}
86+
}')
87+
expect_equal(test_inline(), list("{A}", FALSE))
88+
89+
# test 2, from Enchufa2
90+
# This second example should not compile because of missing parameter verbose
91+
expect_error({
92+
Rcpp::sourceCpp(code='
93+
#include <Rcpp.h>
94+
using namespace Rcpp;
95+
// [[Rcpp::export( rng = false, signature = {x=list("{A}", "B")} )]]
96+
List test_inline(List x, bool verbose=true) {
97+
if(x.size() > 0) {
98+
CharacterVector first_element = x[0];
99+
return List::create(first_element, verbose);
100+
} else {
101+
return List::create(verbose);
102+
}
103+
}')
104+
})
105+
106+
# test 3, from Enchufa2
107+
# This third example should not compile because of missing end bracket }
108+
# The bracket within the signature is taken as the end bracket, which results in
109+
# invalid R code. There are some additional warnings due to the incorrect syntax
110+
expect_warning({
111+
expect_error({
112+
Rcpp::sourceCpp(code='
113+
#include <Rcpp.h>
114+
using namespace Rcpp;
115+
// [[Rcpp::export( rng = false, signature = {x=list("{A}", "B"), verbose=FALSE )]]
116+
List test_inline(List x, bool verbose) {
117+
if(x.size() > 0) {
118+
CharacterVector first_element = x[0];
119+
return List::create(first_element, verbose);
120+
} else {
121+
return List::create(verbose);
122+
}
123+
}', verbose=T)
124+
})
125+
})
126+
127+
# test 4, from Enchufa2
128+
# This 4th example is missing the end bracket and will not compile
129+
expect_error({
130+
Rcpp::sourceCpp(code='
131+
#include <Rcpp.h>
132+
using namespace Rcpp;
133+
// [[Rcpp::export( rng = false, signature = {x=list("A", "B"), verbose=FALSE )]]
134+
List test_inline(List x, bool verbose) {
135+
if(x.size() > 0) {
136+
CharacterVector first_element = x[0];
137+
return List::create(first_element, verbose);
138+
} else {
139+
return List::create(verbose);
140+
}
141+
}')
142+
})
143+
144+
# This 5th example has brackets but incorrect R syntax
145+
expect_error({
146+
Rcpp::sourceCpp(code='
147+
#include <Rcpp.h>
148+
using namespace Rcpp;
149+
// [[Rcpp::export( rng = false, signature = {x=list("A", ###, verbose=FALSE} )]]
150+
List test_inline(List x, bool verbose) {
151+
if(x.size() > 0) {
152+
CharacterVector first_element = x[0];
153+
return List::create(first_element, verbose);
154+
} else {
155+
return List::create(verbose);
156+
}
157+
}')
158+
})
159+
160+
# This 6th example is missing a parameter in the signature
161+
expect_error({
162+
Rcpp::sourceCpp(code='
163+
#include <Rcpp.h>
164+
using namespace Rcpp;
165+
// [[Rcpp::export( rng = false, signature = {x=list("A", "B")} )]]
166+
List test_inline(List x, bool verbose) {
167+
if(x.size() > 0) {
168+
CharacterVector first_element = x[0];
169+
return List::create(first_element, verbose);
170+
} else {
171+
return List::create(verbose);
172+
}
173+
}')
174+
})
175+
176+
177+
remove.packages(pkg, lib="templib")
178+
unlink("templib", recursive = TRUE)
179+
setwd(cwd)
180+
unlink(pkgfile)

0 commit comments

Comments
 (0)