From 13a4d43f940eaf2cc9b5720e21c34860c5c205d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Mon, 9 Apr 2018 14:25:25 +0200 Subject: [PATCH 1/5] start using desc cf #41 --- DESCRIPTION | 6 +++-- R/codemeta_description.R | 49 ++++++++++++++++++-------------------- R/parse_depends.R | 51 ++++++++++++++-------------------------- R/utils.R | 8 ------- codemeta.json | 36 +++++++++++++++++++++------- 5 files changed, 72 insertions(+), 78 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 671dcf18..05d071ca 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -24,14 +24,16 @@ Encoding: UTF-8 LazyData: true RoxygenNote: 6.0.1 Depends: R (>= 3.0.0) -Imports: jsonlite (>= 1.3), +Imports: + jsonlite (>= 1.3), jsonld, git2r, devtools, methods, stats, stringi, - readr + readr, + desc Suggests: testthat, jsonvalidate, covr, diff --git a/R/codemeta_description.R b/R/codemeta_description.R index 76103953..3bdbaa57 100644 --- a/R/codemeta_description.R +++ b/R/codemeta_description.R @@ -17,40 +17,37 @@ new_codemeta <- function() { codemeta_description <- function(f, id = NULL, codemeta = new_codemeta()) { if (file.exists(f)) { - descr <- cm_read_dcf(f) + descr <- desc::desc(f) } else { return(codemeta) } - if (is.null(descr) || length(descr) == 0) { - return(codemeta) - } ## FIXME define an S3 class based on the codemeta list of lists? if (is.null(id)) { - id <- descr$Package + id <- descr$get("Package") } if (is_IRI(id)) { codemeta$`@id` <- id } - codemeta$identifier <- descr$Package - codemeta$description <- descr$Description - codemeta$name <- paste0(descr$Package, ": ", descr$Title) + codemeta$identifier <- descr$get("Package") + codemeta$description <- descr$get("Description") + codemeta$name <- paste0(descr$get("Package"), ": ", + descr$get("Title")) ## Will later guess these these a la devtools::use_github_links - codemeta$codeRepository <- descr$URL - codemeta$issueTracker <- descr$BugReports + codemeta$codeRepository <- descr$get("URL") + codemeta$issueTracker <- descr$get("BugReports") ## According to crosswalk, codemeta$dateModified and ## codemeta$dateCreated are not crosswalked in DESCRIPTION - codemeta$datePublished <- - descr$Date # probably not avaialable as descr$Date. + codemeta$datePublished <- NULL - codemeta$license <- spdx_license(descr$License) + codemeta$license <- spdx_license(descr$get("License")) - codemeta$version <- descr$Version + codemeta$version <- as.character(descr$get_version()) codemeta$programmingLanguage <- list( "@type" = "ComputerLanguage", @@ -64,23 +61,23 @@ codemeta_description <- codemeta$runtimePlatform <- R.version.string if (is.null(codemeta$provider)) - codemeta$provider <- guess_provider(descr$Package) - if ("Authors@R" %in% names(descr)) { + codemeta$provider <- guess_provider(descr$get("Package")) + authors <- try(descr$get_authors(), silent = TRUE) + if (!inherits(authors,'try-error')) { codemeta <- - parse_people(eval(parse(text = descr$`Authors@R`)), codemeta) + parse_people(authors, codemeta) } else { - codemeta <- parse_people(as.person(descr$Author), codemeta) - ## maintainer must come second in case Author list also specifies - ## maintainer by role [cre] without email - codemeta$maintainer <- - person_to_schema(as.person(descr$Maintainer)) + message("No correct Authors@R field in DESCRIPTION, please add authors via Authors@R") # nolint } - codemeta$softwareSuggestions <- parse_depends(descr$Suggests) - codemeta$softwareRequirements <- - c(parse_depends(descr$Imports), - parse_depends(descr$Depends)) + dependencies <- descr$get_deps() + suggests <- dependencies[dependencies$type == "Suggests",] + requirements <- dependencies[dependencies$type %in% + c("Imports", "Depends"),] + + codemeta$softwareSuggestions <- parse_depends(suggests) + codemeta$softwareRequirements <- parse_depends(requirements) diff --git a/R/parse_depends.R b/R/parse_depends.R index dee30ab6..2fb686ad 100644 --- a/R/parse_depends.R +++ b/R/parse_depends.R @@ -1,41 +1,26 @@ ## internal method for parsing a list of package dependencies into pkg URLs +format_depend <- function(package, version){ + dep <- list("@type" = "SoftwareApplication", + identifier = package, + ## FIXME technically the name includes the title + name = package) + + ## Add Version if available + if (version != "*"){ + dep$version <- version + } + + dep$provider <- guess_provider(package) + ## implemention could be better, e.g. support versioning + # dep$`@id` <- guess_dep_id(dep) + dep +} parse_depends <- function(deps) { - if (!is.null(deps)) - str <- strsplit(deps, ",\n*")[[1]] - else - str <- NULL - - lapply(str, function(str) { - #if (length(str) > 1) { - # warning(paste0("package depends", str, "may be multiple packages?")) - #} - - pkg <- gsub("\\s*(\\w+)\\s.*", "\\1", str) - pkg <- gsub("\\s+", "", pkg) - - dep <- list("@type" = "SoftwareApplication", - identifier = pkg, - ## FIXME technically the name includes the title - name = pkg) - - ## Add Version if available - pattern <- "\\s*\\w+\\s+\\([><=]+\\s([1-9.\\-]*)\\)*" - version <- gsub(pattern, "\\1", str) - version <- - gsub("\\)$", "", version) ## hack, avoid extraneous ending ) - has_version <- grepl(pattern, str) - if (has_version) - dep$version <- version - - dep$provider <- guess_provider(pkg) - - ## implemention could be better, e.g. support versioning - # dep$`@id` <- guess_dep_id(dep) - dep - }) + + unname(mapply(format_depend, deps$package, deps$version)) } diff --git a/R/utils.R b/R/utils.R index afdd51c3..7a8903cc 100644 --- a/R/utils.R +++ b/R/utils.R @@ -17,14 +17,6 @@ get_root_path <- function(pkg){ } -## based on devtools::read_dcf -cm_read_dcf <- function(dcf) { - - fields <- colnames(read.dcf(dcf)) - as.list(read.dcf(dcf, keep.white = fields)[1, ]) - -} - ## Like system.file, but pkg can instead be path to package root directory get_file <- function(FILE, pkg = "."){ f <- file.path(pkg, FILE) diff --git a/codemeta.json b/codemeta.json index bcac4ce7..1d953f43 100644 --- a/codemeta.json +++ b/codemeta.json @@ -7,7 +7,6 @@ "identifier": "codemetar", "description": "The 'Codemeta' Project defines a 'JSON-LD' format for describing\n software metadata, as detailed at . This package\n provides utilities to generate, parse, and modify 'codemeta.json' files \n automatically for R packages, as well as tools and examples for working with\n 'codemeta.json' 'JSON-LD' more generally.", "name": "codemetar: Generate 'CodeMeta' Metadata for R Packages", - "issueTracker": "https://github.com/ropensci/codemetar/issues", "license": "https://spdx.org/licenses/MIT", "version": "0.1.5", "programmingLanguage": { @@ -141,7 +140,7 @@ "@type": "SoftwareApplication", "identifier": "dplyr", "name": "dplyr", - "version": "0.7.0", + "version": ">= 0.7.0", "provider": { "@id": "https://cran.r-project.org", "@type": "Organization", @@ -184,11 +183,17 @@ } ], "softwareRequirements": [ + { + "@type": "SoftwareApplication", + "identifier": "R", + "name": "R", + "version": ">= 3.0.0" + }, { "@type": "SoftwareApplication", "identifier": "jsonlite", "name": "jsonlite", - "version": "1.3", + "version": ">= 1.3", "provider": { "@id": "https://cran.r-project.org", "@type": "Organization", @@ -263,18 +268,31 @@ }, { "@type": "SoftwareApplication", - "identifier": "R", - "name": "R", - "version": "3.0.0" + "identifier": "desc", + "name": "desc", + "provider": { + "@id": "https://cran.r-project.org", + "@type": "Organization", + "name": "Central R Archive Network (CRAN)", + "url": "https://cran.r-project.org" + } } ], - "codeRepository": "https://github.com/ropensci/codemetar", "isPartOf": "https://ropensci.org", - "keywords": ["metadata", "codemeta", "ropensci", "citation", "credit", "linked-data"], + "keywords": [ + "metadata", + "codemeta", + "ropensci", + "citation", + "credit", + "linked-data" + ], "relatedLink": "https://codemeta.github.io/codemetar", "contIntegration": "https://travis-ci.org/ropensci/codemetar", "developmentStatus": "active", "releaseNotes": "https://github.com/ropensci/codemetar/blob/master/NEWS.md", "readme": "https://github.com/ropensci/codemetar/blob/master/README.md", - "fileSize": "266.748KB" + "fileSize": "266.286KB", + "codeRepository": "https://github.com/ropensci/codemetar", + "issueTracker": "https://github.com/ropensci/codemetar/issues" } From 826a5f826439633dba99946b336443419a5ef992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Mon, 9 Apr 2018 14:50:51 +0200 Subject: [PATCH 2/5] various fixes --- DESCRIPTION | 5 ++-- R/codemeta_description.R | 2 +- man/codemetar-package.Rd | 4 ++-- tests/testthat/test-codemeta_description.R | 2 +- tests/testthat/test-parse_depends.R | 27 +++++++++++----------- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 05d071ca..b393a38c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -22,7 +22,7 @@ URL: https://github.com/ropensci/codemetar BugReports: https://github.com/ropensci/codemetar/issues Encoding: UTF-8 LazyData: true -RoxygenNote: 6.0.1 +RoxygenNote: 6.0.1.9000 Depends: R (>= 3.0.0) Imports: jsonlite (>= 1.3), @@ -33,7 +33,8 @@ Imports: stats, stringi, readr, - desc + desc, + usethis Suggests: testthat, jsonvalidate, covr, diff --git a/R/codemeta_description.R b/R/codemeta_description.R index 3bdbaa57..c7c7d3ad 100644 --- a/R/codemeta_description.R +++ b/R/codemeta_description.R @@ -67,7 +67,7 @@ codemeta_description <- codemeta <- parse_people(authors, codemeta) } else { - message("No correct Authors@R field in DESCRIPTION, please add authors via Authors@R") # nolint + stop("No correct Authors@R field in DESCRIPTION, please add authors via Authors@R") # nolint } diff --git a/man/codemetar-package.Rd b/man/codemetar-package.Rd index 59ba4504..bc77c67e 100644 --- a/man/codemetar-package.Rd +++ b/man/codemetar-package.Rd @@ -48,8 +48,8 @@ Useful links: Other contributors: \itemize{ - \item Anna Krystalli (0000-0002-2378-4915) [NA] - \item Toph Allen (0000-0003-4580-091X) [NA] + \item Anna Krystalli (0000-0002-2378-4915) [reviewer] + \item Toph Allen (0000-0003-4580-091X) [reviewer] } } diff --git a/tests/testthat/test-codemeta_description.R b/tests/testthat/test-codemeta_description.R index 72f3e7f2..f3d026d2 100644 --- a/tests/testthat/test-codemeta_description.R +++ b/tests/testthat/test-codemeta_description.R @@ -7,6 +7,6 @@ testthat::test_that("We can use a preset id", { testthat::test_that("We can parse plain Authors: & Maintainers: entries", { f <- system.file("examples/DESCRIPTION_ex1.dcf", package = "codemetar") - codemeta_description(f) + expect_error(codemeta_description(f)) }) diff --git a/tests/testthat/test-parse_depends.R b/tests/testthat/test-parse_depends.R index 66883544..1fdc6270 100644 --- a/tests/testthat/test-parse_depends.R +++ b/tests/testthat/test-parse_depends.R @@ -2,23 +2,24 @@ testthat::context("parse_depends.R") testthat::test_that("Test the various cases for dependencies", { - a <- parse_depends(NULL) - testthat::expect_length(a, 0) - a <- parse_depends(deps = "a4") # BIOC provider - testthat::expect_gt(length(a[[1]]), 1) - a <- parse_depends(deps = "httr") # CRAN provider - testthat::expect_gt(length(a[[1]]), 1) - a <- parse_depends(deps = "R") - testthat::expect_equal(a[[1]]$name, "R") - a <- parse_depends(deps = "not-a-package") + testthat::expect_error(format_depend(NULL)) + a <- format_depend(package = "a4", + version = "*") # BIOC provider + testthat::expect_equal(a$provider$`@id`, "https://www.bioconductor.org") + a <- format_depend(package = "httr", + version = "*") # CRAN provider + testthat::expect_equal(a$provider$`@id`, "https://cran.r-project.org") + a <- format_depend(package = "R", + version = ">= 3.0.0") + testthat::expect_equal(a$name, "R") }) testthat::test_that("Test the various cases for ids (NOT used currently)", { - a <- guess_dep_id(parse_depends("a4")[[1]]) # BIOC provider - a <- guess_dep_id(parse_depends("httr")[[1]]) # CRAN provider - a <- guess_dep_id(parse_depends("R")[[1]]) - a <- guess_dep_id(parse_depends("not-a-package")[[1]]) + # a <- guess_dep_id(parse_depends("a4")[[1]]) # BIOC provider + # a <- guess_dep_id(parse_depends("httr")[[1]]) # CRAN provider + # a <- guess_dep_id(parse_depends("R")[[1]]) + # a <- guess_dep_id(parse_depends("not-a-package")[[1]]) }) From d9240be2f8749629cf5092b85d44c0c46284d352 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Mon, 9 Apr 2018 15:10:11 +0200 Subject: [PATCH 3/5] better example? --- R/create_codemeta.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/create_codemeta.R b/R/create_codemeta.R index d01765e9..ce3e1f27 100644 --- a/R/create_codemeta.R +++ b/R/create_codemeta.R @@ -9,7 +9,7 @@ #' @return a codemeta list object #' @export #' @examples -#' cm <- create_codemeta("jsonlite") +#' cm <- create_codemeta("jqr") #' cm$keywords <- list("metadata", "ropensci") #' @importFrom jsonlite read_json create_codemeta <- function(pkg = ".", From b4e6e69e6acd5d3b3866d4b146904e97f4f3db78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Mon, 9 Apr 2018 15:13:23 +0200 Subject: [PATCH 4/5] document --- man/create_codemeta.Rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/create_codemeta.Rd b/man/create_codemeta.Rd index 93174304..452f405e 100644 --- a/man/create_codemeta.Rd +++ b/man/create_codemeta.Rd @@ -29,6 +29,6 @@ to \code{\link{write_codemeta}}, but returns an R list object rather than writing directly to a file. See examples. } \examples{ -cm <- create_codemeta("jsonlite") +cm <- create_codemeta("jqr") cm$keywords <- list("metadata", "ropensci") } From f87969103aeca2c7c3e78464dac404c9a9a80b15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Mon, 9 Apr 2018 15:28:33 +0200 Subject: [PATCH 5/5] removes reference to deleted function --- R/parse_citation.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/parse_citation.R b/R/parse_citation.R index b772d9cf..220e715c 100644 --- a/R/parse_citation.R +++ b/R/parse_citation.R @@ -75,7 +75,7 @@ guess_citation <- function(pkg){ installed <- installed.packages() if(file.exists(file.path(pkg, "inst/CITATION"))){ bib <- readCitationFile(file.path(pkg, "inst/CITATION"), - meta = cm_read_dcf(file.path(pkg, "DESCRIPTION"))) + meta = desc::desc(file.path(pkg, "DESCRIPTION"))) lapply(bib, parse_citation) } else if(pkg %in% installed[,1]){ bib <- suppressWarnings(citation(pkg)) # don't worry if no date