Skip to content

Commit 15d8a0a

Browse files
authored
Merge branch 'devel' into httr2_doi
2 parents 678e809 + 84c17b5 commit 15d8a0a

8 files changed

Lines changed: 267 additions & 4 deletions

File tree

DESCRIPTION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
Package: BiocPkgTools
22
Type: Package
33
Title: Collection of simple tools for learning about Bioconductor Packages
4-
Version: 1.29.2
5-
Date: 2025-10-22
4+
Version: 1.29.4
5+
Date: 2026-03-13
66
Authors@R: c(
77
person("Shian", "Su", role=c("aut", "ctb"), email = "su.s@wehi.edu.au"),
88
person("Lori", "Shepherd", role="ctb", email = "Lori.Shepherd@roswellpark.org"),

R/BiocPkgDOI_mint_by_REST.R

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
2+
#' Generate a DOI for a Bioconductor package
3+
#'
4+
#' This function makes calls out to the REST API (v2) described
5+
#' here: \url{https://support.datacite.org/docs/api-create-dois}. This
6+
#' function creates a new DOI for a Bioconductor package (cannot already
7+
#' exist). The target URL for the DOI is the short Bioconductor
8+
#' package URL.
9+
#'
10+
#' The login information for the "real" Bioconductor account
11+
#' should be stored in the environment variables "EZID_USERNAME"
12+
#' and "EZID_PASSWORD".
13+
#'
14+
#' The GUI is available here: \url{https://doi.datacite.org/}.
15+
#'
16+
#' @param pkg character(1) package name
17+
#' @param authors character vector of authors (will be "pasted" together)
18+
#' @param pubyear integer(1) publication year
19+
#' @param testing logical(1) If true, will use the apitest
20+
#' user with the password apitest. These DOIs will expire.
21+
#' The same apitest:apitest combination can be used to
22+
#' login to the EZID website for doing things using the
23+
#' web interface. If false, the Bioconductor-specific
24+
#' user credentials should be in the correct environment
25+
#' variables
26+
#'
27+
#' @return The DOI as a character(1) vector.
28+
#'
29+
#' @importFrom httr POST status_code PUT authenticate timeout content_type accept content
30+
#'
31+
#' @keywords Internal
32+
#'
33+
#' @examples
34+
#' \dontrun{
35+
#' x = generateBiocPkgDOI('RANDOM_TEST_PACKAGE','Sean Davis',1972)
36+
#' }
37+
#
38+
# draft concept
39+
#
40+
# {
41+
# "data": {
42+
# "type": "dois",
43+
# "attributes": {
44+
# "doi": "10.18129/B9"
45+
# }
46+
# }
47+
# }
48+
# BIOC prefix: 10.18129/B9
49+
# $ curl -X POST -H "Content-Type: application/vnd.api+json" --user YOUR_REPOSITORY_ID:YOUR_PASSWORD -d @my_draft_doi.json https://api.test.datacite.org/dois
50+
#
51+
generateBiocPkgDOI_REST = function(pkg, authors, pubyear, testing=TRUE) {
52+
if(testing) {
53+
# View results at: https://doi.test.datacite.org
54+
# The testing piece does not work with new API?
55+
username='TESTING_USERNAME'
56+
password='TESTING_PASSWORD'
57+
bioc_shoulder='doi:10.5072/FK2'
58+
base_url = 'https://ez.test.datacite.org/id'
59+
} else {
60+
username=Sys.getenv('EZID_USERNAME')
61+
password=Sys.getenv('EZID_PASSWORD')
62+
bioc_shoulder='doi:10.18129/B9'
63+
base_url = "https://ez.datacite.org/id"
64+
}
65+
bioc_doi_namespace = ".bioc."
66+
pkg_doi = paste0(bioc_shoulder,bioc_doi_namespace,pkg)
67+
url0 = file.path(base_url,pkg_doi)
68+
body = paste(c(sprintf("datacite.title: %s",pkg),
69+
sprintf("_target: https://bioconductor.org/packages/%s",pkg),
70+
sprintf("datacite.creator: %s",gsub('\n','',paste(authors,collapse=", "))),
71+
"datacite.publisher: Bioconductor",
72+
sprintf("datacite.publicationyear: %d",pubyear),
73+
sprintf("datacite.resourcetype: %s","Software")),collapse="\n")
74+
res = httr::POST(url0,
75+
content_type('text/plain'),
76+
accept("text/plain"),
77+
httr::authenticate(username,password),
78+
body=body,timeout(30))
79+
if(status_code(res)>=400) {
80+
res = httr::PUT(url0,
81+
content_type('text/plain'),
82+
accept("text/plain"),
83+
httr::authenticate(username,password),
84+
body=body,timeout(30))
85+
}
86+
message(res)
87+
return(res)
88+
tmp = strsplit(content(res),' ')[[1]][c(2,4)]
89+
return(tmp[1])
90+
}

R/biocPkgList.R

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,38 @@
1+
#' Extract funder names from a formatted \code{Author} field string
2+
#'
3+
#' @param author_string character(1) a formatted \code{Author} field value as
4+
#' found in a Bioconductor \code{VIEWS} file, e.g.
5+
#' \code{"Jane Doe [aut, cre], Big Org [fnd]"}. May contain embedded
6+
#' newlines. Note: funder names that themselves contain commas will not be
7+
#' extracted correctly, as commas are used as entry separators in the
8+
#' formatted \code{Author} field.
9+
#'
10+
#' @return character() of funder names, or \code{NA_character_} when no funder
11+
#' is found or the input is missing/empty
12+
#'
13+
#' @keywords internal
14+
.extract_fnd <- function(author_string) {
15+
if (is.na(author_string) || !nzchar(trimws(author_string)))
16+
return(NA_character_)
17+
## Normalise line-continuation whitespace
18+
s <- gsub("\\s*[\n\r]+\\s*", " ", author_string)
19+
## Match author entries whose role bracket contains the "fnd" role
20+
## Format: "Some Name [role1, fnd, role2]"
21+
m <- gregexpr(
22+
"([^,\\[]+?)\\s*\\[([^\\]]*\\bfnd\\b[^\\]]*)\\]",
23+
s, perl = TRUE
24+
)
25+
matches <- regmatches(s, m)[[1L]]
26+
if (!length(matches))
27+
return(NA_character_)
28+
## Strip the trailing "[roles]" to recover just the name
29+
names_only <- trimws(sub("\\s*\\[[^\\]]*\\]$", "", matches))
30+
## Remove any stray leading comma (can occur when the entry is not first)
31+
names_only <- trimws(sub("^,\\s*", "", names_only))
32+
names_only <- names_only[nzchar(names_only)]
33+
if (!length(names_only)) NA_character_ else names_only
34+
}
35+
136
#' @import biocViews
237
#' @importFrom RBGL transitive.closure
338
.computeBiocViewsTransitiveClosure <- function() {
@@ -43,7 +78,12 @@
4378
#' @param addBiocViewParents `logical(1)` whether to add all biocViews
4479
#' parents to biocViews annotations.
4580
#'
46-
#' @return An object of class `tbl_df`.
81+
#' @return An object of class `tbl_df` with one row per package. The result
82+
#' always includes a `fnd` list-column whose elements are character vectors
83+
#' of funder names extracted from persons with role `"fnd"` in the
84+
#' formatted `Author` field. Elements are `NA_character_` for packages
85+
#' that declare no funder (or whose `Author` field contains no `[fnd]`
86+
#' role tag).
4787
#'
4888
#' @importFrom BiocManager repositories version
4989
#' @importFrom stringr str_split str_replace_all str_remove_all str_squish
@@ -135,6 +175,10 @@ biocPkgList <- function(
135175
ret$biocViews = tmp
136176
}
137177

178+
## Extract funder names from the raw (unprocessed) Author
179+
## field while role brackets are still present
180+
ret[["fnd"]] <- lapply(ret[["Author"]], .extract_fnd)
181+
138182
ret[["Author"]] = ret[["Author"]] |>
139183
str_replace_all("\n", " ") |>
140184
str_remove_all("\\[.*?\\]") |>

man/biocPkgList.Rd

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/dot-extract_fnd.Rd

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/generateBiocPkgDOI_REST.Rd

Lines changed: 46 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test_biocPkgList.R

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,8 @@ test_that("nrow is approximately correct", {
1818
expect_gt(nrow(bpkgl), 1000)
1919
})
2020

21+
test_that("fnd column is present and is a list", {
22+
expect_true("fnd" %in% colnames(bpkgl))
23+
expect_type(bpkgl[["fnd"]], "list")
24+
})
25+

tests/testthat/test_getPackageInfo.R

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,52 @@ test_that("getPackageInfo() parses Authors@R", {
3535
aut <- getPackageInfo(fl)[,"Author"]
3636
expect_identical(aut, c(Author = "Iman Author, Im A. Author"))
3737
})
38+
39+
test_that(".extract_fnd() returns NA for no funder", {
40+
expect_identical(
41+
BiocPkgTools:::.extract_fnd(NA_character_),
42+
NA_character_
43+
)
44+
expect_identical(
45+
BiocPkgTools:::.extract_fnd(""),
46+
NA_character_
47+
)
48+
expect_identical(
49+
BiocPkgTools:::.extract_fnd("Jane Doe [aut, cre]"),
50+
NA_character_
51+
)
52+
})
53+
54+
test_that(".extract_fnd() extracts single funder", {
55+
result <- BiocPkgTools:::.extract_fnd(
56+
"Jane Doe [aut], Big Funder [fnd]"
57+
)
58+
expect_identical(result, "Big Funder [fnd]")
59+
})
60+
61+
test_that(".extract_fnd() extracts multiple funders", {
62+
result <- BiocPkgTools:::.extract_fnd(
63+
"Jane Doe [aut], Funder One [fnd], Funder Two [fnd]"
64+
)
65+
expect_length(result, 2L)
66+
expect_identical(result, c("Funder One [fnd]", "Funder Two [fnd]"))
67+
})
68+
69+
test_that(".extract_fnd() extracts funders from multiline Author field", {
70+
author <- paste0(
71+
"Martin Morgan [aut, cre],\n",
72+
" Chan Zuckerberg Initiative DAF CZF2019-002443 [fnd],\n",
73+
" NIH NCI ITCR U24CA180996 [fnd]"
74+
)
75+
result <- BiocPkgTools:::.extract_fnd(author)
76+
expect_length(result, 2L)
77+
expect_identical(result[[1L]], "Chan Zuckerberg Initiative DAF CZF2019-002443 [fnd]")
78+
expect_identical(result[[2L]], "NIH NCI ITCR U24CA180996 [fnd]")
79+
})
80+
81+
test_that(".extract_fnd() returns NA when no [fnd] tag present", {
82+
expect_identical(
83+
BiocPkgTools:::.extract_fnd("some text without role brackets"),
84+
NA_character_
85+
)
86+
})

0 commit comments

Comments
 (0)