diff --git a/.Rbuildignore b/.Rbuildignore index 3174899..824ef7b 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -10,3 +10,5 @@ ^pkgdown$ ^README\.Rmd$ ^CRAN-SUBMISSION$ +^\.positai$ +^\.claude$ diff --git a/.gitignore b/.gitignore index 88c5440..ea9c1f6 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,4 @@ docs # Mac OS .DS_Store +.positai diff --git a/NAMESPACE b/NAMESPACE index 72e42a3..c68b4ce 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -14,6 +14,7 @@ export(remove_resource) export(resource_names) export(resources) export(schema) +export(version) export(write_package) import(rlang) importFrom(readr,problems) diff --git a/NEWS.md b/NEWS.md index 14eace3..f331ccc 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,7 @@ ## For users +* New `version()` determines what version of the Data Package standard is used by a Data Package (e.g. `"1.0"`, `"2.0"`, `">=2.0"`). This based on the presence and value of the `$schema` property (#299). * `read_resource()` now supports reading from remote zip files, thanks to support in `{vroom}` (1.3.0) (#291). * `write_package()` will now print multiple `resource$path` and `resource$schema$missingValues` on multiple lines (#297). * `resources()` is soft-deprecated, please use `resource_names()` instead (#282). diff --git a/R/version.R b/R/version.R new file mode 100644 index 0000000..9d1f103 --- /dev/null +++ b/R/version.R @@ -0,0 +1,43 @@ +#' Get Data Package version +#' +#' Determines what version of the [Data Package standard]( +#' https://datapackage.org/) is used by a Data Package, based on the +#' [`$schema`](https://datapackage.org/standard/data-package/#dollar-schema) +#' property. +#' Version `"1.0"` is assumed if `$schema` is missing, version `">=2.0"` is +#' assumed for custom values (e.g. [extensions]( +#' https://datapackage.org/standard/extensions/)). +#' +#' @inheritParams read_resource +#' @returns Data Package version number (e.g. `"1.0"`). +#' @family version functions +#' @export +#' @examples +#' package <- example_package() +#' version(package) +version <- function(package) { + dollar_schema <- purrr::pluck(package, "$schema") + + if (is.null(dollar_schema)) { + return("1.0") # Assume 1.0 if $schema is undefined + } + if (!is.character(dollar_schema)) { + return(">=2.0") # Assume 2.0 or higher if $schema is present but invalid + } + + # Extract version from e.g. + # "https://datapackage.org/profiles//datapackage.json" + pattern = "^https://datapackage\\.org/profiles/((?:[0-9A-Za-z]|\\.|-)+)/.*" + extracted_version <- sub( + pattern, + "\\1", + dollar_schema, + perl = TRUE + ) + + if (extracted_version == dollar_schema) { + return(">=2.0") # Assume 2.0 or higher if $schema is a custom value + } + + extracted_version +} diff --git a/_pkgdown.yml b/_pkgdown.yml index d82535e..963b7ca 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -31,4 +31,5 @@ reference: - has_concept("accessor functions") - has_concept("print functions") - has_concept("check functions") + - has_concept("version functions") - has_concept("sample data") diff --git a/man/version.Rd b/man/version.Rd new file mode 100644 index 0000000..611b548 --- /dev/null +++ b/man/version.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/version.R +\name{version} +\alias{version} +\title{Get Data Package version} +\usage{ +version(package) +} +\arguments{ +\item{package}{Data Package object, as returned by \code{\link[=read_package]{read_package()}} or +\code{\link[=create_package]{create_package()}}.} +} +\value{ +Data Package version number (e.g. \code{"1.0"}). +} +\description{ +Determines what version of the \href{https://datapackage.org/}{Data Package standard} is used by a Data Package, based on the +\href{https://datapackage.org/standard/data-package/#dollar-schema}{\verb{$schema}} +property. +Version \code{"1.0"} is assumed if \verb{$schema} is missing, version \code{">=2.0"} is +assumed for custom values (e.g. \href{https://datapackage.org/standard/extensions/}{extensions}). +} +\examples{ +package <- example_package() +version(package) +} +\concept{version functions} diff --git a/tests/testthat/test-version.R b/tests/testthat/test-version.R new file mode 100644 index 0000000..ad8e619 --- /dev/null +++ b/tests/testthat/test-version.R @@ -0,0 +1,44 @@ +test_that("version() returns version based on $schema", { + p <- create_package() + + # Undefined + p$`$schema` <- NULL + expect_equal(version(p), "1.0") + + # Defined default + p$`$schema` <- "https://datapackage.org/profiles/1.0/datapackage.json" + expect_equal(version(p), "1.0") + + # 2.0 + p$`$schema` <- "https://datapackage.org/profiles/2.0/datapackage.json" + expect_equal(version(p), "2.0") + + # Future versions + p$`$schema` <- "https://datapackage.org/profiles/2.1/datapackage.json" + expect_equal(version(p), "2.1") + p$`$schema` <- "https://datapackage.org/profiles/2.2-rc.1/datapackage.json" + expect_equal(version(p), "2.2-rc.1") + p$`$schema` <- "https://datapackage.org/profiles/3.0/datapackage.json" + expect_equal(version(p), "3.0") + + # Custom extensions + p$`$schema` <- "https://spatial.datapackage.org/profiles/1.0/datapackage.json" + expect_equal(version(p), ">=2.0") + p$`$schema` <- "http://rs.tdwg.org/dwc-dp/1.0/dwc-dp-profile.json" + expect_equal(version(p), ">=2.0") +}) + +test_that("version() returns >=2.0 for invalid $schema", { + p <- create_package() + p$`$schema` <- list() + expect_equal(version(p), ">=2.0") + p$`$schema` <- 3.0 + expect_equal(version(p), ">=2.0") +}) + +test_that("version() returns correct version for example packages", { + p_1.0 <- example_package(version = "1.0") + expect_equal(version(p_1.0), "1.0") + p_2.0 <- example_package(version = "2.0") + expect_equal(version(p_2.0), "2.0") +})