├── .Rbuildignore ├── .coveralls.yml ├── .github ├── .gitignore ├── issue_template.md ├── pull_request_template.md ├── stale.yml └── workflows │ └── R-CMD-check.yaml ├── .gitignore ├── DESCRIPTION ├── Ffrictionless.png ├── LEAD.md ├── LICENSE ├── NAMESPACE ├── NEWS.Rmd ├── NEWS.md ├── R ├── constraints.R ├── constraints.checkEnum.R ├── constraints.checkMaxLength.R ├── constraints.checkMaximum.R ├── constraints.checkMinLength.R ├── constraints.checkMinimum.R ├── constraints.checkPattern.R ├── constraints.checkRequired.R ├── constraints.checkUnique.R ├── field.R ├── helpers.R ├── infer.R ├── is.valid.R ├── profile.R ├── readable.R ├── readable.array.R ├── readable.connection.R ├── schema.R ├── table.R ├── tableschema.r.R ├── tableschemaerror.R ├── types.R ├── types.castAny.R ├── types.castArray.R ├── types.castBoolean.R ├── types.castDate.R ├── types.castDatetime.R ├── types.castDuration.R ├── types.castGeojson.R ├── types.castGeopoint.R ├── types.castInteger.R ├── types.castList.R ├── types.castNumber.R ├── types.castObject.R ├── types.castString.R ├── types.castTime.R ├── types.castYear.R ├── types.castYearmonth.R ├── validate.R └── writable.R ├── README.Rmd ├── README.md ├── docs ├── 404.html ├── Ffrictionless.png ├── LICENSE-text.html ├── authors.html ├── docsearch.css ├── docsearch.js ├── index.html ├── issue_template.html ├── link.svg ├── news │ └── index.html ├── okgr.png ├── oklabs.png ├── pkgdown.css ├── pkgdown.js ├── pkgdown.yml ├── pull_request_template.html └── reference │ ├── Constraints.html │ ├── DEFAULT_DECIMAL_CHAR.html │ ├── DEFAULT_GROUP_CHAR.html │ ├── FALSE_VALUES.html │ ├── Field.html │ ├── Profile.html │ ├── Profile.load.html │ ├── Readable.html │ ├── ReadableArray.html │ ├── ReadableConnection.html │ ├── Schema.html │ ├── Schema.load.html │ ├── TRUE_VALUES.html │ ├── Table.html │ ├── Table.load.html │ ├── TableSchemaError.html │ ├── Types.html │ ├── Writeable.html │ ├── constraints.checkEnum.html │ ├── constraints.checkMaxLength.html │ ├── constraints.checkMaximum.html │ ├── constraints.checkMinLength.html │ ├── constraints.checkMinimum.html │ ├── constraints.checkPattern.html │ ├── constraints.checkRequired.html │ ├── constraints.checkUnique.html │ ├── durations.html │ ├── helpers.expandFieldDescriptor.html │ ├── helpers.expandSchemaDescriptor.html │ ├── helpers.from.json.to.list.html │ ├── helpers.from.list.to.json.html │ ├── helpers.retrieveDescriptor.html │ ├── index.html │ ├── infer.html │ ├── is.binary.html │ ├── is.email.html │ ├── is.uri.html │ ├── is.uuid.html │ ├── is.valid.html │ ├── is_empty.html │ ├── is_integer.html │ ├── is_object.html │ ├── tableschema.r-package.html │ ├── types.castAny.html │ ├── types.castArray.html │ ├── types.castBoolean.html │ ├── types.castDate.html │ ├── types.castDatetime.html │ ├── types.castDuration.html │ ├── types.castGeojson.html │ ├── types.castGeopoint.html │ ├── types.castInteger.html │ ├── types.castList.html │ ├── types.castNumber.html │ ├── types.castObject.html │ ├── types.castString.html │ ├── types.castTime.html │ ├── types.castYear.html │ ├── types.castYearmonth.html │ ├── validate.html │ └── write_json.html ├── frictionlessdata.png ├── inst ├── config │ └── config.yml ├── extdata │ ├── data.csv │ ├── data_big.csv │ ├── data_delim.csv │ ├── data_delim2.csv │ ├── data_infer.csv │ ├── data_infer_formats.csv │ ├── data_infer_row_limit.csv │ ├── data_infer_utf8.csv │ ├── data_parse_options_default.csv │ ├── data_parse_options_delimiter.csv │ ├── jsonchar.json │ ├── latin1.csv │ ├── mathematics.csv │ ├── mathematics.json │ ├── schema.json │ ├── schema2.json │ └── schema_valid_full.json └── profiles │ ├── geojson.json │ └── tableschema.json ├── man ├── Constraints.Rd ├── DEFAULT_DECIMAL_CHAR.Rd ├── DEFAULT_GROUP_CHAR.Rd ├── FALSE_VALUES.Rd ├── Field.Rd ├── Profile.Rd ├── Profile.load.Rd ├── Readable.Rd ├── ReadableArray.Rd ├── ReadableConnection.Rd ├── Schema.Rd ├── TRUE_VALUES.Rd ├── Table.Rd ├── TableSchemaError.Rd ├── Types.Rd ├── Writeable.Rd ├── constraints.checkEnum.Rd ├── constraints.checkMaxLength.Rd ├── constraints.checkMaximum.Rd ├── constraints.checkMinLength.Rd ├── constraints.checkMinimum.Rd ├── constraints.checkPattern.Rd ├── constraints.checkRequired.Rd ├── constraints.checkUnique.Rd ├── durations.Rd ├── helpers.expandFieldDescriptor.Rd ├── helpers.expandSchemaDescriptor.Rd ├── helpers.from.json.to.list.Rd ├── helpers.from.list.to.json.Rd ├── helpers.retrieveDescriptor.Rd ├── infer.Rd ├── is.binary.Rd ├── is.email.Rd ├── is.uri.Rd ├── is.uuid.Rd ├── is.valid.Rd ├── is_empty.Rd ├── is_integer.Rd ├── is_object.Rd ├── schema.load.Rd ├── table.load.Rd ├── tableschema.r-package.Rd ├── types.castAny.Rd ├── types.castArray.Rd ├── types.castBoolean.Rd ├── types.castDate.Rd ├── types.castDatetime.Rd ├── types.castDuration.Rd ├── types.castGeojson.Rd ├── types.castGeopoint.Rd ├── types.castInteger.Rd ├── types.castList.Rd ├── types.castNumber.Rd ├── types.castObject.Rd ├── types.castString.Rd ├── types.castTime.Rd ├── types.castYear.Rd ├── types.castYearmonth.Rd ├── validate.Rd └── write_json.Rd ├── okgr.png ├── oklabs.png ├── tableschema-r.Rproj └── tests ├── testthat.R └── testthat ├── inst ├── extdata │ ├── data.csv │ ├── data_big.csv │ ├── data_delim.csv │ ├── data_delim2.csv │ ├── data_infer.csv │ ├── data_infer_formats.csv │ ├── data_infer_row_limit.csv │ ├── data_infer_utf8.csv │ ├── data_parse_options_default.csv │ ├── data_parse_options_delimiter.csv │ ├── jsonchar.json │ ├── latin1.csv │ ├── mathematics.csv │ ├── mathematics.json │ ├── schema.json │ ├── schema2.json │ └── schema_valid_full.json └── profiles │ ├── geojson.json │ └── tableschema.json ├── profiles ├── geojson.json └── tableschema.json ├── test-constraints.checkEnum.R ├── test-constraints.checkMaxLength.R ├── test-constraints.checkMaximum.R ├── test-constraints.checkMinLength.R ├── test-constraints.checkMinimum.R ├── test-constraints.checkPattern.R ├── test-constraints.checkRequired.R ├── test-constraints.checkUnique.R ├── test-errors.R ├── test-field.R ├── test-helpers.R ├── test-infer.R ├── test-profile.R ├── test-schema.R ├── test-table-general.R ├── test-table-relations.R ├── test-types.castAny.R ├── test-types.castArray.R ├── test-types.castBoolean.R ├── test-types.castDate.R ├── test-types.castDatetime.R ├── test-types.castDuration.R ├── test-types.castGeojson.R ├── test-types.castGeopoint.R ├── test-types.castInteger.R ├── test-types.castList.R ├── test-types.castNumber.R ├── test-types.castObject.R ├── test-types.castString.R ├── test-types.castTime.R ├── test-types.castYear.R ├── test-types.castYearmonth.R └── test-validate.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^packrat/ 4 | ^\.Rprofile$ 5 | ^NEWS\.Rmd$ 6 | ^README\.Rmd$ 7 | ^config\.yml$ 8 | ^frictionlessdata\.png$ 9 | ^okgr\.png$ 10 | ^oklabs\.png$ 11 | ^tableschema-r\.rxproj$ 12 | ^tableschema-r\.sln$ 13 | ^\.coveralls\.yml$ 14 | ^\.idea$ 15 | ^field\.R\.annot\.R$ 16 | ^codecov\.yml$ 17 | ^\.github 18 | ^Ffrictionless\.png 19 | ^docs$ 20 | ^LEAD\.md 21 | ^MAKEFILE 22 | ^\.github$ 23 | -------------------------------------------------------------------------------- /.coveralls.yml: -------------------------------------------------------------------------------- 1 | repo_token: hBte7T1ELqwIgCxxz3vzMTkNs07WvABgK -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | Please replace this line with full information about your idea or problem. If it's a bug share as much as possible to reproduce it 4 | 5 | --- 6 | 7 | Please preserve this line to notify @kleanthisk10 (lead of this repository) 8 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | Please replace this line with full information about your pull request. Make sure that tests pass before publishing it 4 | 5 | --- 6 | 7 | Please preserve this line to notify @kleanthisk10 (lead of this repository) 8 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 90 3 | 4 | # Number of days of inactivity before a stale issue is closed 5 | daysUntilClose: 30 6 | 7 | # Issues with these labels will never be considered stale 8 | exemptLabels: 9 | - feature 10 | - enhancement 11 | - bug 12 | 13 | # Label to use when marking an issue as stale 14 | staleLabel: wontfix 15 | 16 | # Comment to post when marking an issue as stale. Set to `false` to disable 17 | markComment: > 18 | This issue has been automatically marked as stale because it has not had 19 | recent activity. It will be closed if no further activity occurs. Thank you 20 | for your contributions. 21 | 22 | # Comment to post when closing a stale issue. Set to `false` to disable 23 | closeComment: false 24 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | 8 | name: R-CMD-check.yaml 9 | 10 | permissions: read-all 11 | 12 | jobs: 13 | R-CMD-check: 14 | runs-on: ${{ matrix.config.os }} 15 | 16 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 17 | 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | config: 22 | - {os: macos-latest, r: 'release'} 23 | - {os: windows-latest, r: 'release'} 24 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 25 | - {os: ubuntu-latest, r: 'release'} 26 | - {os: ubuntu-latest, r: 'oldrel-1'} 27 | 28 | env: 29 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 30 | R_KEEP_PKG_SOURCE: yes 31 | 32 | steps: 33 | - uses: actions/checkout@v4 34 | 35 | - uses: r-lib/actions/setup-pandoc@v2 36 | 37 | - uses: r-lib/actions/setup-r@v2 38 | with: 39 | r-version: ${{ matrix.config.r }} 40 | http-user-agent: ${{ matrix.config.http-user-agent }} 41 | use-public-rspm: true 42 | 43 | - uses: r-lib/actions/setup-r-dependencies@v2 44 | with: 45 | extra-packages: any::rcmdcheck 46 | needs: check 47 | 48 | - uses: r-lib/actions/check-r-package@v2 49 | with: 50 | upload-snapshots: true 51 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")' 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # History files 2 | .Rhistory 3 | .Rapp.history 4 | 5 | # Session Data files 6 | .RData 7 | # Example code in package build process 8 | *-Ex.R 9 | # Output files from R CMD build 10 | /*.tar.gz 11 | # Output files from R CMD check 12 | /*.Rcheck/ 13 | # RStudio files 14 | .Rproj.user/ 15 | # produced vignettes 16 | vignettes/*.html 17 | vignettes/*.pdf 18 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 19 | .httr-oauth 20 | # knitr and R markdown default cache directories 21 | /*_cache/ 22 | /cache/ 23 | # Temporary files created by R markdown 24 | *.utf8.md 25 | *.knit.md 26 | .Rproj.user 27 | /R/person.R 28 | /.vs/ 29 | packrat/lib*/ 30 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: tableschema.r 2 | Type: Package 3 | Title: Table Schema 'Frictionless Data' 4 | Version: 1.1.3 5 | Date: 2022-09-29 6 | Authors@R: c(person("Kleanthis", "Koupidis", email = "koupidis@okfn.gr", role = c("aut", "cre")), 7 | person("Lazaros", "Ioannidis", email = "larjohn@gmail.com", role = "aut"), 8 | person("Charalampos", "Bratsas", email = "cbratsas@math.auth.gr", role = "aut"), 9 | person("Open Knowledge International", email = "info@okfn.org", role = "cph")) 10 | Maintainer: Kleanthis Koupidis 11 | Description: Allows to work with 'Table Schema' (). 'Table Schema' is well suited for use cases around handling and validating tabular data in text formats such as 'csv', but its utility extends well beyond this core usage, towards a range of applications where data benefits from a portable schema format. The 'tableschema.r' package can load and validate any table schema descriptor, allow the creation and modification of descriptors, expose methods for reading and streaming data that conforms to a 'Table Schema' via the 'Tabular Data Resource' abstraction. 12 | URL: https://github.com/frictionlessdata/tableschema-r 13 | BugReports: https://github.com/frictionlessdata/tableschema-r/issues 14 | License: MIT + file LICENSE 15 | Encoding: UTF-8 16 | LazyData: true 17 | Imports: 18 | config, 19 | future, 20 | httr, 21 | jsonlite, 22 | jsonvalidate, 23 | lubridate, 24 | purrr, 25 | R6, 26 | RCurl, 27 | rlist, 28 | stringr, 29 | urltools 30 | Suggests: 31 | covr, 32 | foreach, 33 | testthat 34 | Collate: 35 | 'constraints.checkUnique.R' 36 | 'constraints.checkRequired.R' 37 | 'constraints.checkPattern.R' 38 | 'constraints.checkMinLength.R' 39 | 'constraints.checkMinimum.R' 40 | 'constraints.checkMaxLength.R' 41 | 'constraints.checkMaximum.R' 42 | 'constraints.checkEnum.R' 43 | 'constraints.R' 44 | 'types.castArray.R' 45 | 'types.castYearmonth.R' 46 | 'types.castYear.R' 47 | 'types.castTime.R' 48 | 'types.castString.R' 49 | 'types.castObject.R' 50 | 'types.castNumber.R' 51 | 'types.castList.R' 52 | 'types.castInteger.R' 53 | 'types.castGeopoint.R' 54 | 'types.castGeojson.R' 55 | 'types.castDuration.R' 56 | 'types.castDatetime.R' 57 | 'types.castDate.R' 58 | 'types.castBoolean.R' 59 | 'types.castAny.R' 60 | 'types.R' 61 | 'field.R' 62 | 'helpers.R' 63 | 'infer.R' 64 | 'is.valid.R' 65 | 'tableschemaerror.R' 66 | 'profile.R' 67 | 'readable.R' 68 | 'readable.array.R' 69 | 'readable.connection.R' 70 | 'schema.R' 71 | 'table.R' 72 | 'tableschema.r.R' 73 | 'validate.R' 74 | 'writable.R' 75 | RoxygenNote: 7.3.1 76 | Roxygen: list(r6 = FALSE) 77 | -------------------------------------------------------------------------------- /Ffrictionless.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frictionlessdata/tableschema-r/f5f40bdfca2044753fbbd0f2aeebd1b5e4041181/Ffrictionless.png -------------------------------------------------------------------------------- /LEAD.md: -------------------------------------------------------------------------------- 1 | kleanthisk10 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2018 2 | COPYRIGHT HOLDER: Open Knowledge International -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(Constraints) 4 | export(DEFAULT_DECIMAL_CHAR) 5 | export(DEFAULT_GROUP_CHAR) 6 | export(FALSE_VALUES) 7 | export(Field) 8 | export(Profile) 9 | export(Profile.load) 10 | export(Readable) 11 | export(ReadableArray) 12 | export(ReadableConnection) 13 | export(Schema) 14 | export(Schema.load) 15 | export(TRUE_VALUES) 16 | export(Table) 17 | export(Table.load) 18 | export(TableSchemaError) 19 | export(Types) 20 | export(Writeable) 21 | export(constraints.checkEnum) 22 | export(constraints.checkMaxLength) 23 | export(constraints.checkMaximum) 24 | export(constraints.checkMinLength) 25 | export(constraints.checkMinimum) 26 | export(constraints.checkPattern) 27 | export(constraints.checkRequired) 28 | export(constraints.checkUnique) 29 | export(durations) 30 | export(helpers.expandFieldDescriptor) 31 | export(helpers.expandSchemaDescriptor) 32 | export(helpers.from.json.to.list) 33 | export(helpers.from.list.to.json) 34 | export(helpers.retrieveDescriptor) 35 | export(infer) 36 | export(is.binary) 37 | export(is.email) 38 | export(is.uri) 39 | export(is.uuid) 40 | export(is.valid) 41 | export(is_empty) 42 | export(is_integer) 43 | export(is_object) 44 | export(types.castAny) 45 | export(types.castArray) 46 | export(types.castBoolean) 47 | export(types.castDate) 48 | export(types.castDatetime) 49 | export(types.castDuration) 50 | export(types.castGeojson) 51 | export(types.castGeopoint) 52 | export(types.castInteger) 53 | export(types.castList) 54 | export(types.castNumber) 55 | export(types.castObject) 56 | export(types.castString) 57 | export(types.castTime) 58 | export(types.castYear) 59 | export(types.castYearmonth) 60 | export(validate) 61 | export(write_json) 62 | importFrom(R6,R6Class) 63 | -------------------------------------------------------------------------------- /NEWS.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "NEWS" 3 | output: 4 | github_document: 5 | html_preview: yes 6 | --- 7 | #### tableschema-r v1.1.3 8 | 9 | update roxygen documentation 10 | 11 | #### tableschema-r v1.1.2 12 | 13 | update links in documentation 14 | 15 | #### tableschema-r v1.1.1 16 | 17 | add tests, improve castboolean, cast_time and check required 18 | 19 | ---------------------------------------------------------------- 20 | 21 | #### tableschema-r v1.1 22 | 23 | Auto detect delimiter , or ; 24 | 25 | ---------------------------------------------------------------- 26 | 27 | #### tableschema-r v1.0 28 | 29 | The library based on the Frictionless Data specs v1 - https://specs.frictionlessdata.io//table-schema/ 30 | 31 | ---------------------------------------------------------------- 32 | 33 | #### tableschema-r v0.1 34 | 35 | First stable version of the library. 36 | 37 | ---------------------------------------------------------------- 38 | 39 | #### tableschema-r v0.0.0.9000 40 | 41 | Complete types, formats and result value of cast. 42 | 43 | ---------------------------------------------------------------- -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | NEWS 2 | ================ 3 | 4 | #### tableschema-r v1.1.3 5 | 6 | update roxygen documentation 7 | 8 | #### tableschema-r v1.1.2 9 | 10 | update links in documentation 11 | 12 | #### tableschema-r v1.1.1 13 | 14 | add tests, improve castboolean, cast_time and check required 15 | 16 | ------------------------------------------------------------------------ 17 | 18 | #### tableschema-r v1.1 19 | 20 | Auto detect delimiter , or ; 21 | 22 | ------------------------------------------------------------------------ 23 | 24 | #### tableschema-r v1.0 25 | 26 | The library based on the Frictionless Data specs v1 - 27 | 28 | 29 | ------------------------------------------------------------------------ 30 | 31 | #### tableschema-r v0.1 32 | 33 | First stable version of the library. 34 | 35 | ------------------------------------------------------------------------ 36 | 37 | #### tableschema-r v0.0.0.9000 38 | 39 | Complete types, formats and result value of cast. 40 | 41 | ------------------------------------------------------------------------ 42 | -------------------------------------------------------------------------------- /R/constraints.R: -------------------------------------------------------------------------------- 1 | #' Constraints class 2 | #' @description R6 class with constraints. 3 | #' 4 | #' The constraints property on Table Schema Fields can be used by consumers to list constraints for 5 | #' validating field values. For example, validating the data in a Tabular Data Resource against 6 | #' its Table Schema; or as a means to validate data being collected or updated via a data entry interface. 7 | #' 8 | #' All constraints \code{MUST} be tested against the logical representation of data, and the physical 9 | #' representation of constraint values \code{MAY} be primitive types as possible in JSON, 10 | #' or represented as strings that are castable with the type and format rules of the field. 11 | #' 12 | #' 13 | #' @docType class 14 | #' @importFrom R6 R6Class 15 | #' @export 16 | #' @keywords data 17 | #' @return Object of \code{\link{R6Class}} . 18 | #' @format \code{\link{R6Class}} object. 19 | #' 20 | #' @field constraints see Section See Also 21 | #' 22 | #' @include constraints.checkEnum.R 23 | #' @include constraints.checkMaximum.R 24 | #' @include constraints.checkMaxLength.R 25 | #' @include constraints.checkMinimum.R 26 | #' @include constraints.checkMinLength.R 27 | #' @include constraints.checkPattern.R 28 | #' @include constraints.checkRequired.R 29 | #' @include constraints.checkUnique.R 30 | #' 31 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications}, 32 | #' \code{\link{constraints.checkEnum}}, 33 | #' \code{\link{constraints.checkMaximum}}, 34 | #' \code{\link{constraints.checkMaxLength}}, 35 | #' \code{\link{constraints.checkMinimum}}, 36 | #' \code{\link{constraints.checkMinLength}}, 37 | #' \code{\link{constraints.checkPattern}}, 38 | #' \code{\link{constraints.checkRequired}}, 39 | #' \code{\link{constraints.checkUnique}} 40 | 41 | Constraints <- R6Class("Constraints", public = list(constraints = list( 42 | 43 | checkEnum = constraints.checkEnum, 44 | checkMaximum = constraints.checkMaximum, 45 | checkMaxLength = constraints.checkMaxLength, 46 | checkMinimum = constraints.checkMinimum, 47 | checkMinLength = constraints.checkMinLength, 48 | checkPattern = constraints.checkPattern, 49 | checkRequired = constraints.checkRequired, 50 | checkUnique = constraints.checkUnique 51 | 52 | ))) 53 | -------------------------------------------------------------------------------- /R/constraints.checkEnum.R: -------------------------------------------------------------------------------- 1 | #' Check Enum 2 | #' @description Check if the value is exactly match a constraint. 3 | #' @param constraint numeric list,matrix or vector with the constraint values 4 | #' @param value numeric value to meet the constraint 5 | #' @return TRUE if value meets the constraint 6 | #' @rdname constraints.checkEnum 7 | #' @export 8 | #' 9 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications} 10 | #' 11 | #' @examples 12 | #' 13 | #' constraints.checkEnum(constraint = list(1, 2), value = 1) 14 | #' 15 | #' constraints.checkEnum(constraint = list(1, 2), value = 3) 16 | 17 | constraints.checkEnum <- function(constraint, value) { 18 | 19 | if (is.null(value)) return(TRUE) 20 | 21 | if (all(value %in% constraint)) return(TRUE) 22 | 23 | return(FALSE) 24 | 25 | } 26 | -------------------------------------------------------------------------------- /R/constraints.checkMaxLength.R: -------------------------------------------------------------------------------- 1 | #' Check if maximum character length constraint is met 2 | #' @description Specify the maximum length of a character 3 | #' @param constraint numeric constraint, maximum character length 4 | #' @param value character to meet the constraint 5 | #' @return TRUE if character length is equal to or less than the constraint 6 | #' @rdname constraints.checkMaxLength 7 | #' @export 8 | #' 9 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications} 10 | #' 11 | #' @examples 12 | #' 13 | #' constraints.checkMaxLength(constraint = list(2), value = "hi") 14 | #' 15 | #' constraints.checkMaxLength(constraint = 2, value = "hello") 16 | 17 | constraints.checkMaxLength <- function(constraint, value) { 18 | 19 | if (is.null(value)) return(TRUE) 20 | 21 | if (all(nchar(value) <= constraint)) return(TRUE) 22 | 23 | return(FALSE) 24 | } 25 | -------------------------------------------------------------------------------- /R/constraints.checkMaximum.R: -------------------------------------------------------------------------------- 1 | #' Check if maximum constraint is met 2 | #' @description Specifies a maximum value for a field. This is different to \code{maxLength} which checks the number of items in the value. 3 | #' A maximum value constraint checks whether a field value is equal to or less than the specified value. 4 | #' The range checking depends on the type of the field. E.g. an integer field may have a maximum value of 100. 5 | #' If a maximum value constraint is specified then the field descriptor \code{MUST} contain a type key. 6 | #' 7 | #' @param constraint numeric constraint value 8 | #' @param value numeric value to meet the constraint 9 | #' @return TRUE if value is equal to or less than the constraint 10 | #' @rdname constraints.checkMaximum 11 | #' @export 12 | #' 13 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications} 14 | #' 15 | #' @examples 16 | #' 17 | #' constraints.checkMaximum(constraint = list(2), value = 1) 18 | #' 19 | #' constraints.checkMaximum(constraint = 2, value = 3) 20 | #' 21 | 22 | constraints.checkMaximum <- function(constraint, value) { 23 | 24 | if (is.null(value)) return(TRUE) 25 | 26 | if (all(value <= constraint)) return(TRUE) 27 | 28 | return(FALSE) 29 | 30 | } -------------------------------------------------------------------------------- /R/constraints.checkMinLength.R: -------------------------------------------------------------------------------- 1 | #' Check if minimum character length constraint is met 2 | #' @description Specify the minimum length of a character 3 | #' @param constraint numeric constraint, minimum character length 4 | #' @param value character to meet the constraint 5 | #' @return TRUE if character length is equal to or greater than the constraint 6 | #' @rdname constraints.checkMinLength 7 | #' @export 8 | #' 9 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications} 10 | #' 11 | #' @examples 12 | #' 13 | #' constraints.checkMinLength(constraint = list(3), value = "hi") 14 | #' 15 | #' constraints.checkMinLength(constraint = 2, value = "hello") 16 | 17 | constraints.checkMinLength <- function(constraint, value){ 18 | 19 | if (is.null(value)) return(TRUE) 20 | 21 | if (all(nchar(value) >= constraint)) return(TRUE) 22 | 23 | return(FALSE) 24 | } -------------------------------------------------------------------------------- /R/constraints.checkMinimum.R: -------------------------------------------------------------------------------- 1 | #' Check if minimum constraint is met 2 | #' @description Specifies a minimum value for a field. This is different to \code{minLength} which checks the number of items in the value. 3 | #' A minimum value constraint checks whether a field value is greater than or equal to the specified value. 4 | #' The range checking depends on the type of the field. E.g. an integer field may have a minimum value of 100. 5 | #' If a minimum value constraint is specified then the field descriptor \code{MUST} contain a type key. 6 | #' 7 | #' @param constraint numeric constraint value 8 | #' @param value numeric value to meet the constraint 9 | #' @return TRUE if value is equal to or greater than the constraint 10 | #' @rdname constraints.checkMinimum 11 | #' @export 12 | #' 13 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications} 14 | #' 15 | #' @examples 16 | #' 17 | #' constraints.checkMinimum(constraint = list(2), value = 1) 18 | #' 19 | #' constraints.checkMinimum(constraint = 2, value = 3) 20 | 21 | constraints.checkMinimum <- function(constraint, value) { 22 | 23 | if (is.null(value)) return(TRUE) 24 | 25 | if (all(value >= constraint)) return(TRUE) 26 | 27 | return(FALSE) 28 | 29 | } -------------------------------------------------------------------------------- /R/constraints.checkPattern.R: -------------------------------------------------------------------------------- 1 | #' Pattern matching 2 | #' @description Search for pattern matches (value) within a character vector (constraint). 3 | #' A regular expression is used to test field values. 4 | #' If the regular expression matches then the value is valid. 5 | #' The values of this field \code{MUST} conform to the standard 6 | #' \href{http://www.w3.org/TR/xmlschema-2/#regexs}{XML Schema regular expression syntax}. 7 | #' 8 | #' @param constraint character vector where matches are sought 9 | #' @param value character string to be matched 10 | #' @return TRUE if the pattern constraint is met 11 | #' @rdname constraints.checkPattern 12 | #' @export 13 | #' 14 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications} 15 | #' 16 | #' @examples 17 | #' 18 | #' constraints.checkPattern(constraint = '^test$', value = 'test') 19 | #' 20 | #' constraints.checkPattern(constraint = '^test$', value = 'TEST') 21 | 22 | constraints.checkPattern <- function(constraint, value) { 23 | 24 | if (is.null(value)) return(TRUE) 25 | 26 | if (isTRUE(grepl(constraint, value))) return(TRUE) 27 | 28 | return(FALSE) 29 | 30 | } 31 | -------------------------------------------------------------------------------- /R/constraints.checkRequired.R: -------------------------------------------------------------------------------- 1 | #' Check if a field is required 2 | #' @description Indicates whether this field is allowed to be \code{NULL}. 3 | #' If required is \code{TRUE}, then \code{NULL} is disallowed. 4 | #' See the section on \href{https://specs.frictionlessdata.io//table-schema/#missing-values}{missingValues} for how, 5 | #' in the physical representation of the data, strings can represent \code{NULL} values. 6 | #' 7 | #' @param constraint set TRUE to check required values 8 | #' @param value value to check 9 | #' @return TRUE if field is required 10 | #' @rdname constraints.checkRequired 11 | #' @export 12 | #' 13 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications} 14 | #' 15 | #' @examples 16 | #' 17 | #' constraints.checkRequired(constraint = FALSE, value = 1) 18 | #' 19 | #' constraints.checkRequired(constraint = TRUE, value = 0) 20 | #' 21 | #' constraints.checkRequired(constraint = TRUE, value = NULL) 22 | #' 23 | #' constraints.checkRequired(constraint = TRUE, value = "undefined") 24 | #' 25 | 26 | constraints.checkRequired <- function(constraint, value) { 27 | 28 | if (!(isTRUE(constraint) && (is.null(value) | 29 | isTRUE(value == "undefined") | 30 | exists(deparse(substitute(value)))))) { 31 | return(TRUE) 32 | } 33 | 34 | return(FALSE) 35 | } 36 | -------------------------------------------------------------------------------- /R/constraints.checkUnique.R: -------------------------------------------------------------------------------- 1 | #' Check if a field is unique 2 | #' @description If \code{TRUE}, then all values for that field \code{MUST} be unique within the data file in which it is found. 3 | #' @param constraint set TRUE to check unique values 4 | #' @param value value to check 5 | #' @return TRUE if field is unique 6 | #' @rdname constraints.checkUnique 7 | #' 8 | #' @export 9 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications} 10 | #' 11 | #' @examples 12 | #' 13 | #' constraints.checkUnique(constraint = FALSE, value = "any") 14 | #' 15 | #' constraints.checkUnique(constraint = TRUE, value = "any") 16 | #' 17 | 18 | constraints.checkUnique <- function(constraint, value) { 19 | 20 | if (isTRUE(value == "any") ) return(TRUE) #!anyDuplicated(value) | 21 | 22 | return(TRUE) 23 | 24 | } -------------------------------------------------------------------------------- /R/infer.R: -------------------------------------------------------------------------------- 1 | #' Infer source schema 2 | #' @description Given data source and headers infer will return a Table Schema based on the data values. 3 | #' @param source data source, one of: 4 | #' \itemize{ 5 | #' \item string with the local CSV file (path) 6 | #' \item string with the remote CSV file (url) 7 | #' \item list of lists representing the rows 8 | #' \item readable stream with CSV file contents 9 | #' \item function returning readable stream with CSV file contents 10 | #' } 11 | #' @param options any \code{Table.load} options 12 | #' @rdname infer 13 | #' @export 14 | #' @return Schema descriptor 15 | #' @examples 16 | #' # list of lists data source 17 | #' source = list( 18 | #' list("id"= 1, 19 | #' "age"= 39, 20 | #' "name"= "Paul"), 21 | #' list("id"= 2, 22 | #' "age"= 23, 23 | #' "name"= "Jimmy"), 24 | #' list("id"= 3, 25 | #' "age"= 36, 26 | #' "name"= "Jane"), 27 | #' list("id"= 4, 28 | #' "age"= 28, 29 | #' "name"= "Judy")) 30 | #' 31 | #' infer(source, options=list(headers=list("id","age","name")))$fields 32 | #' 33 | 34 | # Module API 35 | 36 | infer <- function(source, options = list()) { 37 | 38 | # https://github.com/frictionlessdata/tableschema-js#infer 39 | arguments <- list(source) 40 | arguments <- append(arguments, options) 41 | 42 | def2 <- do.call(Table.load, arguments ) 43 | table <- future::value(def2) 44 | 45 | 46 | descriptor <- table$infer(limit = options[["limit"]]) 47 | 48 | return(descriptor) 49 | } 50 | -------------------------------------------------------------------------------- /R/is.valid.R: -------------------------------------------------------------------------------- 1 | #' @title Is valid 2 | #' @description Validate a descriptor over a schema 3 | #' @param descriptor descriptor, one of: 4 | #' \itemize{ 5 | #' \item string with the local CSV file (path) 6 | #' \item string with the remote CSV file (url) 7 | #' \item list object 8 | #' } 9 | #' @param schema Contents of the json schema, or a filename containing a schema 10 | #' @return \code{TRUE} if valid 11 | #' @rdname is.valid 12 | #' @export 13 | #' 14 | 15 | is.valid <- function(descriptor, schema = NULL) { 16 | 17 | if (is.null(schema)) { 18 | #local 19 | v <- jsonvalidate::json_validator(paste(readLines(system.file('profiles/tableschema.json', package = "tableschema.r"), warn = FALSE, n = -1L), collapse = "")) 20 | } else { 21 | v <- jsonvalidate::json_validator(schema) 22 | #validate = jsonvalidate::json_validate(descriptor, schema) 23 | } 24 | validate <- v(descriptor, verbose = TRUE, greedy = TRUE) 25 | 26 | class(validate) <- "logical" 27 | 28 | validation <- list(valid = validate, errors = attr(validate,"errors")) 29 | 30 | return(validation) 31 | } 32 | -------------------------------------------------------------------------------- /R/readable.R: -------------------------------------------------------------------------------- 1 | #' Readable class 2 | #' @description Readable class that allows typed access to its members 3 | #' @docType class 4 | #' @importFrom R6 R6Class 5 | #' @export 6 | #' @include constraints.R 7 | #' @include tableschemaerror.R 8 | #' @include profile.R 9 | #' @keywords data 10 | #' @return Object of \code{\link{R6Class}}. 11 | #' @format \code{\link{R6Class}} object. 12 | #' 13 | 14 | Readable <- R6Class( 15 | "Readable", 16 | 17 | public = list( 18 | initialize = function(options = list()) { 19 | }, 20 | 21 | read = function(size = NULL) { 22 | future::future( { 23 | while (TRUE) { 24 | if (length(private$buffer_) < 3) { 25 | 26 | chunk <- private$read_(size) 27 | private$buffer_ <- rlist::list.append(private$buffer_, chunk) 28 | } 29 | } 30 | }) 31 | }, 32 | 33 | pipe = function(destination, options = list()) { 34 | private$pipeDestination_ <- destination 35 | self$read() 36 | 37 | destination$on.drain <- private$pipeDrained_ 38 | 39 | private$flowing_ <- TRUE 40 | return(destination) 41 | 42 | }, 43 | unpipe = function(destination) { 44 | 45 | }, 46 | pause = function() { 47 | 48 | }, 49 | resume = function() { 50 | 51 | }, 52 | setEncoding = function() { 53 | 54 | }, 55 | isPaused = function() { 56 | 57 | }, 58 | unshift = function(chunk) { 59 | }, 60 | destroy = function() { 61 | private$destroy_() 62 | }, 63 | 64 | push = function(chunk, encoding) { 65 | 66 | }, 67 | 68 | onData = function(chunk){ 69 | if (private$flowing_) { 70 | } 71 | }, 72 | 73 | on.close = function(handler, unsubscribe = FALSE) { 74 | private$subscribeUnsubscribe_('close', handler, unsubscribe) 75 | }, 76 | 77 | on.data = function(handler, unsubscribe = FALSE) { 78 | private$subscribeUnsubscribe_('data', handler, unsubscribe) 79 | }, 80 | 81 | on.end = function(handler, unsubscribe = FALSE) { 82 | private$subscribeUnsubscribe_('end', handler, unsubscribe) 83 | }, 84 | 85 | on.error = function(handler, unsubscribe = FALSE) { 86 | private$subscribeUnsubscribe_('error', handler, unsubscribe) 87 | }, 88 | 89 | on.readable = function(handler, unsubscribe = FALSE) { 90 | private$subscribeUnsubscribe_('readable', handler, unsubscribe) 91 | } 92 | ), 93 | 94 | active = list( 95 | destroyed = function(value) { 96 | } 97 | ), 98 | 99 | private = list( 100 | encoding_ = NULL, 101 | objectMode_ = FALSE, 102 | read_ = function() { 103 | browser() 104 | }, 105 | destroy_ = function() { 106 | 107 | }, 108 | buffer_ = list(), 109 | readable_ = TRUE, 110 | paused_ = TRUE, 111 | pipeDestination_ = list(), 112 | flowing_ = FALSE, 113 | 114 | pipeDrained_ = function(){ 115 | chunk <- private$buffer[[1]] 116 | rlist::list.remove(private$buffer,1) 117 | private$pipeDestination$write(chunk) 118 | }, 119 | 120 | eventHandlers_ = list( 121 | 'close' = list(), 122 | data = list(), 123 | end = list(), 124 | error = list(), 125 | readable = list() 126 | ), 127 | 128 | emit_ = function(event, arguments = list()) { 129 | for (handler in private$eventHandlers_[[event]]) { 130 | handler(arguments) 131 | } 132 | }, 133 | subscribeUnsubscribe_ = function(event, handler, unsubscribe = FALSE) { 134 | if (!unsubscribe) { 135 | rlist::list.append(private$eventHandlers_[[event]], handler) 136 | } 137 | else { 138 | rlist::list.remove(private$eventHandlers_[[event]], function(eventHandler) { 139 | return(identical(eventHandler, handler)) 140 | }) 141 | } 142 | } 143 | ) 144 | ) 145 | -------------------------------------------------------------------------------- /R/readable.array.R: -------------------------------------------------------------------------------- 1 | #' ReadableArray class 2 | #' @description Readable Array class 3 | #' @docType class 4 | #' @importFrom R6 R6Class 5 | #' @export 6 | #' @include constraints.R 7 | #' @include tableschemaerror.R 8 | #' @include profile.R 9 | #' @keywords data 10 | #' @return Object of \code{\link{R6Class}} . 11 | #' @format \code{\link{R6Class}} object. 12 | #' 13 | 14 | ReadableArray <- R6Class( 15 | "ReadableArray", 16 | inherit = Readable, 17 | public = list( 18 | initialize = function(options = list()) { 19 | 20 | private$array_ <- options$source 21 | 22 | }, 23 | 24 | iterable = function(){ 25 | 26 | return(iterators::iter(function(){ 27 | 28 | if (private$index_ <= length(private$array_)) { 29 | value <- private$array_[[private$index_]] 30 | private$index_ <- private$index_ + 1 31 | 32 | return(value) 33 | } 34 | else { 35 | stop('StopIteration') 36 | } 37 | })) 38 | } 39 | ), 40 | 41 | private = list( 42 | 43 | index_ = 1, 44 | 45 | array_ = list(), 46 | 47 | read_ = function(size) { 48 | return(private$array_) 49 | }, 50 | destroy_ = function() { 51 | } 52 | ) 53 | ) 54 | -------------------------------------------------------------------------------- /R/readable.connection.R: -------------------------------------------------------------------------------- 1 | #' ReadableConnection class 2 | #' @description Readable connection class 3 | #' @docType class 4 | #' @importFrom R6 R6Class 5 | #' @export 6 | #' @include constraints.R 7 | #' @include tableschemaerror.R 8 | #' @include profile.R 9 | #' @keywords data 10 | #' @return Object of \code{\link{R6Class}} . 11 | #' @format \code{\link{R6Class}} object. 12 | ReadableConnection <- R6Class( 13 | "ReadableConnection", 14 | inherit = Readable, 15 | public = list( 16 | initialize = function(options = list()) { 17 | 18 | private$connection_ <- options$source 19 | 20 | }, 21 | 22 | iterable = function() { 23 | 24 | open(private$connection_) 25 | return(iterators::iter(function(){ 26 | if (length(oneLine <- readLines(private$connection_, n = 1, warn = FALSE)) > 0) { 27 | numfields <- count.fields(textConnection(oneLine), sep = ";") 28 | if (numfields[[1]] == 1) delim <- ',' else delim <- ';' 29 | 30 | value <- as.list(strsplit(x = oneLine, 31 | split = paste0(delim,'(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))'), 32 | perl = TRUE)[[1]]) 33 | 34 | 35 | # value <- as.list((strsplit(oneLine, delim))[[1]]) 36 | private$index_ <- private$index_ + 1 37 | 38 | return(value) 39 | 40 | } 41 | 42 | else { 43 | close(private$connection_) 44 | stop('StopIteration') 45 | } 46 | 47 | })) 48 | } 49 | 50 | 51 | 52 | 53 | ), 54 | 55 | private = list( 56 | 57 | index_ = 1, 58 | 59 | connection_ = NULL, 60 | 61 | read_ = function(size) { 62 | return(private$connection_) 63 | }, 64 | destroy_ = function() { 65 | close.connection(private$connection_) 66 | } 67 | 68 | 69 | 70 | ) 71 | ) 72 | -------------------------------------------------------------------------------- /R/tableschema.r.R: -------------------------------------------------------------------------------- 1 | #' @title Table Schema Package 2 | #' 3 | #' @description Table class for working with data and schema 4 | #' 5 | #' @section Introduction: 6 | #' Table Schema is a simple language- and implementation-agnostic way to declare a schema for tabular data. It is well suited for handling and validating tabular data in text formats such as CSV, but its utility extends to many applications where a portable schema format is beneficial. 7 | #' 8 | #' 9 | #' @section Tabular data: 10 | #' Tabular data consists of rows, where each row contains a consistent set of fields (columns). In CSV or spreadsheet formats, the first row is typically used as the header row. In other data systems like SQL, headers (field names) are explicitly defined. 11 | #' 12 | #' @section Physical and logical representation: 13 | #' The \emph{physical representation} of tabular data refers to its format as stored on disk (e.g., CSV, JSON), where data may or may not carry type information. In contrast, the \emph{logical representation} reflects how data is structured and typed after parsing, as defined by the schema specification. 14 | #' 15 | #' For example, \code{constraints} should be applied to the logical representation, while \code{missingValues} are handled during the parsing of the physical format. 16 | #' 17 | #' @section Descriptor: 18 | #' A Table Schema is defined using a descriptor, which \code{MUST} be a JSON object (see \href{https://www.ietf.org/rfc/rfc4627.txt}{RFC 4627}). The descriptor \code{MUST} include a \code{fields} property (array of field descriptors) and \code{MAY} include additional optional properties. 19 | #' 20 | #' @section Field Descriptors: 21 | #' See \code{\link{Field}} class. 22 | #' 23 | #' @section Types and Formats: 24 | #' See \code{\link{Types}} class. 25 | #' 26 | #' @section Constraints: 27 | #' See \code{\link{Constraints}} class. 28 | #' 29 | #' @section Other Properties: 30 | #' Table-level properties include keys, missing value indicators, and metadata. 31 | #' 32 | #' @section Missing Values: 33 | #' Missing values may be indicated using empty strings or placeholders such as \code{"-"} or \code{"NaN"}. The \code{missingValues} property defines which string values are treated as nulls, and applies during parsing. 34 | #' 35 | #' \code{missingValues} \code{MUST} be a list of strings. For example: 36 | #' \itemize{ 37 | #' \item \code{missingValues = list("")} 38 | #' \item \code{missingValues = list("-")} 39 | #' \item \code{missingValues = list("NaN", "-")} 40 | #' } 41 | #' 42 | #' @section Primary Key: 43 | #' The \code{primaryKey} property \code{MAY} be: 44 | #' \itemize{ 45 | #' \item A string (for a single field). 46 | #' \item A list of strings (for a composite key). 47 | #' } 48 | #' 49 | #' @section Foreign Keys: 50 | #' The \code{foreignKeys} property, if present, \code{MUST} be a list of foreign key objects. Each \code{foreignKey} object \code{MUST} include: 51 | #' 52 | #' \describe{ 53 | #' \item{\code{fields}}{A string or list of strings specifying the source field(s).} 54 | #' \item{\code{reference}}{An object with: 55 | #' \describe{ 56 | #' \item{\code{resource}}{The referenced resource name. Use \code{""} for self-referencing keys.} 57 | #' \item{\code{fields}}{The target field(s) on the referenced resource.} 58 | #' } 59 | #' } 60 | #' } 61 | #' 62 | #' \strong{Comment:} Foreign keys create links between Table Schemas. Typically, schemas are part of a larger Data Package, where resources and schemas are associated. 63 | #' 64 | #' @section Details: 65 | #' \itemize{ 66 | #' \item \href{https://CRAN.R-project.org/package=jsonlite}{jsonlite} is used to convert JSON to R list objects. Inputs can be JSON strings, lists, or files; outputs are R lists. 67 | #' \item \href{https://CRAN.R-project.org/package=future}{future} allows asynchronous creation of Table/Schema objects. Use \code{value()} to retrieve results. 68 | #' } 69 | #' 70 | #' See examples in individual functions for using `jsonlite` and `future` with \code{tableschema.r}. 71 | #' 72 | #' The term "array" in JSON corresponds to R \code{list} objects. 73 | #' 74 | #' @section Language: 75 | #' The key words \code{MUST}, \code{MUST NOT}, \code{REQUIRED}, \code{SHALL}, \code{SHALL NOT}, \code{SHOULD}, \code{SHOULD NOT}, \code{RECOMMENDED}, \code{MAY}, and \code{OPTIONAL} are interpreted as described in \href{https://www.ietf.org/rfc/rfc2119.txt}{RFC 2119}. 76 | #' 77 | #' @seealso 78 | #' \href{https://specs.frictionlessdata.io//table-schema/}{Table Schema Specifications} 79 | #' 80 | "_PACKAGE" 81 | 82 | NULL -------------------------------------------------------------------------------- /R/tableschemaerror.R: -------------------------------------------------------------------------------- 1 | #' TableSchemaError class 2 | #' @description Error class for Table Schema 3 | #' @docType class 4 | #' @importFrom R6 R6Class 5 | #' @export 6 | #' @include types.R 7 | #' @include constraints.R 8 | #' @keywords data 9 | #' @return Object of \code{\link{R6Class}} . 10 | #' @format \code{\link{R6Class}} object. 11 | #' 12 | #' @field message 13 | #' @field error 14 | #' @param message message 15 | #' @param error error 16 | TableSchemaError <- R6Class( 17 | "TableSchemaError", 18 | public = list( 19 | message = NULL, 20 | error = NULL, 21 | initialize = function(message, error = NULL){ 22 | self$message <- message 23 | self$error <- error 24 | }), 25 | active = list( 26 | multiple = function() { 27 | if (length(self$error) %in% c(0,1)) return(FALSE) else return(TRUE) 28 | }, 29 | errors = function() { 30 | return(as.list(self$error)) 31 | } 32 | ) 33 | ) 34 | -------------------------------------------------------------------------------- /R/types.R: -------------------------------------------------------------------------------- 1 | #' Types class 2 | #' @description R6 class with Types and Formats. 3 | #' 4 | #' \code{type} and \code{format} properties are used to give the type of the field (string, number etc) - 5 | #' see \href{https://specs.frictionlessdata.io//table-schema/#types-and-formats}{types and formats} for more details. 6 | #' If type is not provided a consumer should assume a type of "string". 7 | #' 8 | #' A field's \code{type} property is a string indicating the type of this field. 9 | #' 10 | #' A field's \code{format} property is a string, indicating a format for the field type. 11 | #' 12 | #' Both \code{type} and format are optional: in a field descriptor, the absence of a \code{type} property indicates that 13 | #' the field is of the type "string", and the absence of a \code{format} property indicates that the field's type \code{format} is "default". 14 | #' 15 | #' Types are based on the \href{https://datatracker.ietf.org/doc/html/draft-zyp-json-schema-03#section-5.1}{type set of json-schema} 16 | #' with some additions and minor modifications (cf other type lists include those in 17 | #' \href{http://www.elasticsearch.org/guide/reference/mapping/}{Elasticsearch types}). 18 | #' 19 | #' @docType class 20 | #' @importFrom R6 R6Class 21 | #' @export 22 | #' @keywords data 23 | #' @field casts see Section See also 24 | #' @return Object of \code{\link{R6Class}} . 25 | #' @format \code{\link{R6Class}} object. 26 | #' @include types.castAny.R 27 | #' @include types.castBoolean.R 28 | #' @include types.castDate.R 29 | #' @include types.castDatetime.R 30 | #' @include types.castDuration.R 31 | #' @include types.castGeojson.R 32 | #' @include types.castGeopoint.R 33 | #' @include types.castInteger.R 34 | #' @include types.castList.R 35 | #' @include types.castNumber.R 36 | #' @include types.castObject.R 37 | #' @include types.castString.R 38 | #' @include types.castTime.R 39 | #' @include types.castYear.R 40 | #' @include types.castYearmonth.R 41 | #' @include types.castArray.R 42 | #' 43 | #' 44 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#types-and-formats}{Types and formats specifications}, 45 | #' \code{\link{types.castAny}}, 46 | #' \code{\link{types.castBoolean}}, 47 | #' \code{\link{types.castDate}}, 48 | #' \code{\link{types.castDatetime}}, 49 | #' \code{\link{types.castDuration}}, 50 | #' \code{\link{types.castGeojson}}, 51 | #' \code{\link{types.castGeopoint}}, 52 | #' \code{\link{types.castInteger}}, 53 | #' \code{\link{types.castList}}, 54 | #' \code{\link{types.castNumber}}, 55 | #' \code{\link{types.castObject}}, 56 | #' \code{\link{types.castString}}, 57 | #' \code{\link{types.castTime}}, 58 | #' \code{\link{types.castYear}}, 59 | #' \code{\link{types.castYearmonth}}, 60 | #' \code{\link{types.castArray}} 61 | #' 62 | 63 | Types <- R6Class("Types", public = list(casts = list( 64 | 65 | castAny = types.castAny, 66 | castArray = types.castArray, 67 | castBoolean = types.castBoolean, 68 | castDate = types.castDate, 69 | castDatetime = types.castDatetime, 70 | castDuration = types.castDuration, 71 | castGeojson = types.castGeojson, 72 | castGeopoint = types.castGeopoint, 73 | castInteger = types.castInteger, 74 | castList = types.castList, 75 | castNumber = types.castNumber, 76 | castObject = types.castObject, 77 | castString = types.castString, 78 | castTime = types.castTime, 79 | castYear = types.castYear, 80 | castYearmonth = types.castYearmonth 81 | ))) 82 | -------------------------------------------------------------------------------- /R/types.castAny.R: -------------------------------------------------------------------------------- 1 | #' @title Cast any value 2 | #' @description Cast any value 3 | #' @param format any format is accepted 4 | #' @param value any value to cast 5 | #' @rdname types.castAny 6 | #' @export 7 | #' @details Any type or format is accepted. 8 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#any}{Types and formats specifications} 9 | #' 10 | #' @examples 11 | #' 12 | #' types.castAny(format = "default", value = 1) 13 | #' 14 | #' types.castAny(format = "default", value = "1") 15 | #' 16 | #' types.castAny(format = "default", value = "") 17 | #' 18 | #' types.castAny(format = "default", value = TRUE) 19 | #' 20 | 21 | types.castAny <- function(format, value) { 22 | return(value) 23 | } -------------------------------------------------------------------------------- /R/types.castArray.R: -------------------------------------------------------------------------------- 1 | #' @title Cast array 2 | #' @description Cast array is used for list objects 3 | #' @param format no options (other than the default) 4 | #' @param value lists, or valid JSON format arrays to cast 5 | #' @rdname types.castArray 6 | #' @export 7 | #' 8 | #' @seealso \code{\link{types.castList}}, 9 | #' \href{https://specs.frictionlessdata.io//table-schema/#array}{Types and formats specifications} 10 | #' 11 | types.castArray <- function(format, value) { 12 | # .Deprecated(new = "types.castList", msg = "'types.castArray' is deprecated.\n Use 'types.castList' instead.") 13 | types.castList(format, value) 14 | } 15 | -------------------------------------------------------------------------------- /R/types.castBoolean.R: -------------------------------------------------------------------------------- 1 | #' @title Cast boolean 2 | #' @description Cast boolean values 3 | #' @param format no options (other than the default) 4 | #' @param value boolean to cast 5 | #' @param options specify additioanl true values or/and falsevalues 6 | #' @rdname types.castBoolean 7 | #' @export 8 | #' @details 9 | #' In the physical representations of data where boolean values are represented with strings, 10 | #' the values set in \code{trueValues} and \code{falseValues} are to be cast to their logical representation as booleans. 11 | #' \code{trueValues} and \code{falseValues} are lists which can be customised to user need. 12 | #' The default values for these are in the additional properties section below. 13 | #' 14 | #' The boolean field can be customised with these additional properties: 15 | #' \itemize{ 16 | #' \item{trueValues: ["true", "True", "TRUE", "1"]} 17 | #' \item{falseValues: ["false", "False", "FALSE", "0"]} 18 | #' } 19 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#boolean}{Types and formats specifications} 20 | #' 21 | #' @examples 22 | #' 23 | #' types.castBoolean(format = "default", value = TRUE) 24 | #' 25 | #' types.castBoolean(format = "default", value = "true") 26 | #' 27 | #' types.castBoolean(format = "default", value = "1") 28 | #' 29 | #' types.castBoolean(format = "default", value = "0") 30 | #' 31 | #' # set options with additional true value 32 | #' types.castBoolean(format = "default", value = "yes", list(trueValues = list("yes"))) 33 | #' 34 | #' # set options with additional false value 35 | #' types.castBoolean(format = "default", value = "no", list(falseValues = list("no"))) 36 | #' 37 | 38 | types.castBoolean <- function(format = "default", value, options={}) { #format parameter is not used 39 | 40 | if ("trueValues" %in% names(options) || "_TRUE_VALUES" %in% names(options)) TRUE_VALUES <- options[["trueValues"]] 41 | 42 | if ("falseValues" %in% names(options)|| "_FALSE_VALUES" %in% names(options)) FALSE_VALUES <- options[["falseValues"]] 43 | 44 | 45 | if (!is.logical(value)) { 46 | 47 | if (!is.character(value)) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 48 | 49 | value <- trimws(value) 50 | 51 | if (value %in% TRUE_VALUES) { 52 | 53 | value <- TRUE 54 | 55 | } else if (value %in% FALSE_VALUES) { 56 | 57 | value <- FALSE 58 | 59 | } else { 60 | 61 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 62 | 63 | } 64 | } 65 | 66 | return(value) 67 | 68 | } 69 | 70 | 71 | 72 | #' default true values 73 | #' @export 74 | TRUE_VALUES <- c("true", "True", "TRUE", "1") 75 | 76 | #' default false values 77 | #' @export 78 | 79 | FALSE_VALUES <- c("false", "False", "FALSE", "0") 80 | -------------------------------------------------------------------------------- /R/types.castDatetime.R: -------------------------------------------------------------------------------- 1 | #' @title Cast datetime 2 | #' @description Cast date with time 3 | #' @param format available options are "default", "any", and "" where 4 | #' \describe{ 5 | #' \item{\code{default }}{An ISO8601 format string e.g. YYYY-MM-DDThh:mm:ssZ in UTC time} 6 | #' \item{\code{any }}{As for \code{\link{types.castDate}}} 7 | #' \item{\code{ }}{As for \code{\link{types.castDate}}} 8 | #' } 9 | #' @param value datetime to cast 10 | #' @rdname types.castDatetime 11 | #' @export 12 | #' 13 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#datetime}{Types and formats specifications}, 14 | #' \code{\link[base]{strptime}}, \code{\link[base]{DateTimeClasses}}, 15 | #' \code{\link[parsedate]{parsedate-package}} and 16 | #' \code{\link[lubridate]{lubridate-package}}. 17 | #' 18 | #' @examples 19 | #' 20 | #' types.castDatetime(format = "default", value = "2014-01-01T06:00:00Z") 21 | #' 22 | #' types.castDatetime(format = "%d/%m/%y %H:%M", value = "21/11/06 16:30") 23 | #' 24 | #format.Date(strptime(value, format="%Y-%m-%dT%H:%M:%SZ"), orders = "%Y-%m-%dT%H:%M:%SZ") 25 | types.castDatetime <- function(format = "%Y-%m-%dT%H:%M:%SZ", value) { 26 | 27 | if (!lubridate::is.Date(value)) { 28 | 29 | if (!is.character(value)) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 30 | 31 | value <- tryCatch({ 32 | if (format == 'default') { 33 | value <- lubridate::as_datetime(lubridate::fast_strptime(value, "%Y-%m-%dT%H:%M:%SZ" )) 34 | } 35 | else if (format == 'any') { 36 | value <- lubridate::force_tz(as.POSIXct(value, tz = 'UTC'), 'UTC') 37 | } 38 | else{ 39 | if (startsWith(format, 'fmt:')) { 40 | format <- gsub('fmt:', '', format) 41 | } 42 | value <- lubridate::as_datetime(lubridate::fast_strptime(value, format)) 43 | } 44 | if (is.na(value)) { 45 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 46 | } 47 | return(value) 48 | }, 49 | 50 | warning = function(w) { 51 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 52 | }, 53 | error = function(e) { 54 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 55 | }) 56 | } 57 | return(value) 58 | } 59 | -------------------------------------------------------------------------------- /R/types.castGeojson.R: -------------------------------------------------------------------------------- 1 | #' @title Cast JSON object according to GeoJSON or TopoJSON spec 2 | #' @description Cast JSON object according to GeoJSON or TopoJSON spec 3 | #' @param format default is a geojson object as per the \href{https://geojson.org/}{GeoJSON spec} or 4 | #' topojson object as per the \href{https://github.com/topojson/topojson-specification/blob/master/README.md}{TopoJSON spec} 5 | #' @param value GeoJSON to cast 6 | #' @rdname types.castGeojson 7 | #' @export 8 | #' 9 | #' 10 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#geojson}{Types and formats specifications} 11 | #' 12 | types.castGeojson <- function(format, value) { 13 | 14 | if (!is.object(value)) { 15 | 16 | if (!is.character(value)) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 17 | 18 | value <- tryCatch( { 19 | 20 | value <- jsonlite::fromJSON(value) 21 | }, 22 | 23 | warning = function(w) { 24 | 25 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 26 | 27 | }, 28 | 29 | error = function(e) { 30 | 31 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 32 | 33 | }, 34 | 35 | finally = { 36 | 37 | }) 38 | 39 | } 40 | 41 | # if(value == config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))){ 42 | # return(value) 43 | # } 44 | 45 | if (format == "default") { 46 | 47 | value <- tryCatch( { 48 | 49 | path_geojson <- system.file("profiles/geojson.json", package = "tableschema.r") 50 | 51 | v <- jsonvalidate::json_validator(path_geojson) 52 | 53 | valid <- v(value,verbose = TRUE, greedy = TRUE, error = FALSE) # ./inst/profiles/geojson.json 54 | 55 | if (!isTRUE(valid)) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 56 | 57 | else return(value) 58 | 59 | }, 60 | 61 | error = function(e) { 62 | 63 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 64 | 65 | }, 66 | 67 | finally = { 68 | 69 | }) 70 | 71 | } else if (format == "topojson") { 72 | 73 | 74 | if ( !is_object(value) ) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) #!isPlainObject(value) 75 | 76 | } 77 | 78 | return(value) 79 | } 80 | 81 | # path_geojson <- system.file("profiles/geojson.json", package = "tableschema.r") 82 | # path_table_schema <- system.file("profiles/table-schema.json", package = "tableschema.r") -------------------------------------------------------------------------------- /R/types.castGeopoint.R: -------------------------------------------------------------------------------- 1 | #' @title Cast geographic point 2 | #' @description Cast geographic point 3 | #' @param format available options are "default", "array" and "object", where 4 | #' \describe{ 5 | #' \item{\code{default }}{A string of the pattern "lon, lat", where \code{lon} is the longitude 6 | #' and \code{lat} is the latitude (note the space is optional after the \code{,}). E.g. \code{"90, 45"}.} 7 | #' \item{\code{array }}{A JSON array, or a string parsable as a JSON array, of exactly two items, 8 | #' where each item is a number, and the first item is \code{lon} and the second item is \code{lat} e.g. \code{[90, 45]}.} 9 | #' \item{\code{object }}{A JSON object with exactly two keys, \code{lat} and \code{lon} and each value is a number e.g. \code{{"lon": 90, "lat": 45}}.} 10 | #' } 11 | #' @param value geopoint to cast 12 | #' @rdname types.castGeopoint 13 | #' @export 14 | #' 15 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#geopoint}{Types and formats specifications} 16 | #' 17 | #' @examples 18 | #' 19 | #' types.castGeopoint(format = "default", value = list(180, 90)) 20 | #' 21 | #' types.castGeopoint(format = "default", value = '180,90') 22 | #' 23 | #' types.castGeopoint(format = "default", value = '180, -90') 24 | #' 25 | #' types.castGeopoint(format = "array", value = list(180, 90)) 26 | #' 27 | #' types.castGeopoint(format = "array", value = '[180, -90]') 28 | #' 29 | #' types.castGeopoint(format = "object", value = list(lon = 180, lat = 90)) 30 | #' 31 | #' types.castGeopoint(format = "object", value = '{"lon": 180, "lat": 90}') 32 | #' 33 | 34 | types.castGeopoint <- function(format, value) { 35 | 36 | tryCatch({ 37 | 38 | lon_lat <- list() 39 | 40 | if (format == 'default') { 41 | 42 | if (is.character(value)) { 43 | 44 | lon_lat <- as.list(unlist(strsplit(value, ","))) 45 | 46 | lon_lat[[1]] <- trimws(lon_lat[[1]], which = "both") 47 | lon_lat[[2]] <- trimws(lon_lat[[2]], which = "both") 48 | 49 | } else if (is.array(value) | is.list(value)) { 50 | 51 | lon_lat <- value 52 | 53 | } else return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 54 | 55 | } else if (format == 'array' | format == 'list') { 56 | 57 | if (is.character(value)) { 58 | 59 | value <- jsonlite::fromJSON(value, simplifyVector = FALSE) 60 | 61 | } 62 | 63 | lon_lat <- value 64 | 65 | } else if (format == 'object') { 66 | 67 | if (is.character(value)) { 68 | 69 | value <- jsonlite::fromJSON(value) 70 | 71 | } 72 | 73 | lon_lat[[1]] <- value[[1]] 74 | lon_lat[[2]] <- value[[2]] 75 | 76 | } 77 | 78 | lon_lat[[1]] <- as.numeric(lon_lat[[1]]) 79 | lon_lat[[2]] <- as.numeric(lon_lat[[2]]) 80 | 81 | }, 82 | 83 | error = function(e) { 84 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 85 | }) 86 | 87 | 88 | if (is_empty(lon_lat) | is.null(lon_lat) | !is.null(names(lon_lat)) ) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 89 | 90 | if (length(lon_lat) != 2) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 91 | 92 | if (is.nan(lon_lat[[1]]) | lon_lat[[1]] > 180 | lon_lat[[1]] < -180) { 93 | 94 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 95 | 96 | } 97 | 98 | if (is.nan(lon_lat[[2]]) | lon_lat[[2]] > 90 | lon_lat[[2]] < -90) { 99 | 100 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 101 | 102 | } 103 | 104 | return(lon_lat) 105 | } 106 | -------------------------------------------------------------------------------- /R/types.castInteger.R: -------------------------------------------------------------------------------- 1 | #' @title Cast integer 2 | #' @description Cast integer. Integer values are indicated in the standard way for any valid integer. 3 | #' @param format no options (other than the default) 4 | #' @param value integer to cast 5 | #' @param options named list set bareNumber \code{TRUE} or \code{FALSE}, see details 6 | #' 7 | #' @details 8 | #' bareNumber is a boolean field with a default of \code{TRUE}. If \code{TRUE} the physical contents of this field must follow 9 | #' the formatting constraints already set out. If \code{FALSE} the contents of this field may contain leading 10 | #' and or trailing non-numeric characters (which implementors MUST therefore strip). 11 | #' The purpose of \code{bareNumber} is to allow publishers to publish numeric data that contains trailing characters such as percentages 12 | #' e.g. \code{95}% or leading characters such as currencies e.g. €\code{95} or EUR \code{95}. Note that it is entirely up to implementors what, 13 | #' if anything, they do with stripped text. 14 | #' 15 | #' @rdname types.castInteger 16 | #' 17 | #' @export 18 | #' 19 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#integer}{Types and formats specifications} 20 | #' 21 | #' @examples 22 | #' types.castInteger(format = "default", value = 1) 23 | #' 24 | #' types.castInteger(format = "default", value = "1") 25 | #' # cast trailing non numeric character 26 | #' types.castInteger(format = "default", value = "1$", options = list(bareNumber = FALSE)) 27 | #' 28 | 29 | types.castInteger <- function(format, value, options={}) { 30 | 31 | if (!is_integer(value)) { 32 | 33 | if (!is.character(value)) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 34 | 35 | if ("bareNumber" %in% names(options)) { 36 | 37 | bareNumber <- options[["bareNumber"]] 38 | 39 | if (bareNumber == FALSE) { 40 | 41 | #value = gsub("(^\\D*)|(\\D*$)", value, "", value) 42 | value <- stringr::str_replace_all(string = value, pattern = "(^\\D*)|(\\D*$)", replacement = "") #gsub("\\s", "", value) 43 | 44 | } 45 | } 46 | 47 | value <- tryCatch({ 48 | 49 | result <- as.integer(value) 50 | 51 | if (is.nan(result) || as.character(result) != value) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 52 | 53 | value <- result 54 | 55 | }, 56 | 57 | warning = function(w) { 58 | 59 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 60 | 61 | }, 62 | 63 | error = function(e) { 64 | 65 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 66 | 67 | }, 68 | 69 | finally = {}) 70 | 71 | } 72 | 73 | return(value) 74 | } 75 | -------------------------------------------------------------------------------- /R/types.castList.R: -------------------------------------------------------------------------------- 1 | #' @title Cast list 2 | #' @description cast list 3 | #' @param format no options (other than the default) 4 | #' @param value lists, or valid JSON format arrays to cast 5 | #' @rdname types.castList 6 | #' @export 7 | #' 8 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#array}{Types and formats specifications} 9 | #' 10 | #' @examples 11 | #' 12 | #' types.castList(format = "default", value = list()) 13 | #' 14 | #' types.castList(format = "default", value = list('key', 'value')) 15 | #' 16 | #' types.castList(format = "default", value = '["key", "value"]') # cast valid json array 17 | #' 18 | 19 | types.castList <- function(format, value) { 20 | 21 | if (!is.list(value)) { 22 | if (!is.character(value)) { 23 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 24 | } 25 | } 26 | 27 | if (is.list(value)) { 28 | return(value) 29 | 30 | } else if (isTRUE(jsonlite::validate(value))) { 31 | 32 | value <- tryCatch({ 33 | 34 | helpers.from.json.to.list(value) 35 | 36 | }, 37 | warning = function(w) { 38 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 39 | }, 40 | 41 | error = function(e) { 42 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 43 | 44 | }, 45 | 46 | finally = { 47 | 48 | }) 49 | } 50 | 51 | if (!is.list(value) ) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 52 | 53 | return(value) 54 | 55 | } 56 | -------------------------------------------------------------------------------- /R/types.castObject.R: -------------------------------------------------------------------------------- 1 | #' @title Cast object 2 | #' @description Cast object data which is lists or valid JSON. 3 | #' @param format no options (other than the default) 4 | #' @param value object to cast 5 | #' @rdname types.castObject 6 | #' @export 7 | #' 8 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#object}{Types and formats specifications} 9 | #' 10 | #' @examples 11 | #' 12 | #' types.castObject(format = "default", value = list()) 13 | #' 14 | #' types.castObject(format = "default", value = "{}") 15 | #' 16 | #' types.castObject(format = "default", value = '{"key": "value"}') 17 | #' 18 | types.castObject <- function(format, value) { 19 | 20 | if (!is_object(value)) { 21 | if (!is.character(value)) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 22 | } 23 | 24 | if (is.list(value)) { 25 | return(value) 26 | 27 | } else if (isTRUE(jsonlite::validate(value))) { 28 | 29 | value <- tryCatch({ 30 | helpers.from.json.to.list(value) 31 | }, 32 | warning = function(w) { 33 | return(config::get("WARNING", file = system.file("config/config.yml", package = "tableschema.r"))) 34 | }, 35 | error = function(e) { 36 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 37 | }, 38 | finally = { 39 | }) 40 | } 41 | 42 | if (any(!is.list(value) | is.null(names(value)))) { 43 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 44 | } 45 | return(value) 46 | } 47 | -------------------------------------------------------------------------------- /R/types.castString.R: -------------------------------------------------------------------------------- 1 | #' @title Cast string 2 | #' @description Cast string that is, sequences of characters. 3 | #' @param format available options are "default", "email", "uri", "binary" and "uuid", where 4 | #' \describe{ 5 | #' \item{\code{default }}{Any valid string.} 6 | #' \item{\code{email }}{A valid email address.} 7 | #' \item{\code{uri }}{A valid URI.} 8 | #' \item{\code{binary }}{A base64 encoded string representing binary data.} 9 | #' \item{\code{uuid }}{A string that is a uuid.} 10 | #' } 11 | #' @param value string to cast 12 | #' 13 | #' @rdname types.castString 14 | #' 15 | #' @export 16 | #' 17 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#string}{Types and formats specifications} 18 | #' 19 | #' @examples 20 | #' 21 | #' # cast any string 22 | #' types.castString(format = "default", value = "string") 23 | #' 24 | #' # cast email 25 | #' types.castString(format = "email", value = "name@gmail.com") 26 | #' \dontshow{ 27 | #' # cast uri 28 | #' types.castString(format = "uri", value = "http://google.com") 29 | #' } 30 | #' # cast binary 31 | #' types.castString(format = "binary", value = "dGVzdA==") 32 | #' 33 | #' # cast uuid 34 | #' types.castString(format = "uuid", value = "95ecc380-afe9-11e4-9b6c-751b66dd541e") 35 | #' 36 | 37 | types.castString <- function(format, value) { 38 | 39 | if (!is.character(value) && length(value) > 0) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 40 | 41 | if (!is.null(format) && format == "uri") { 42 | 43 | if (!is.uri(value)) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 44 | 45 | } else if (!is.null(format) && format == "email") { 46 | 47 | if (!is.email(value)) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 48 | 49 | } else if (!is.null(format) && format == "uuid") { 50 | 51 | if (!is.uuid(value)) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 52 | 53 | 54 | } else if (!is.null(format) && format == "binary") { 55 | 56 | if (!is.binary(value)) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 57 | 58 | } 59 | 60 | return(value) 61 | 62 | } 63 | -------------------------------------------------------------------------------- /R/types.castTime.R: -------------------------------------------------------------------------------- 1 | #' @title Cast time without a date 2 | #' @description Cast time without a date 3 | #' @param format available options are "default", "any", and "" where 4 | #' \describe{ 5 | #' \item{\code{default }}{An ISO8601 time string e.g. hh:mm:ss} 6 | #' \item{\code{any }}{As for \code{\link{types.castDate}}} 7 | #' \item{\code{ }}{As for \code{\link{types.castDate}}} 8 | #' } 9 | #' @param value time to cast 10 | #' 11 | #' @rdname types.castTime 12 | #' 13 | #' @export 14 | #' 15 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#time}{Types and formats specifications}, 16 | #' \code{\link[base]{strptime}}, \code{\link[base]{DateTimeClasses}}, 17 | #' \code{\link[parsedate]{parsedate-package}} and 18 | #' \code{\link[lubridate]{lubridate-package}}. 19 | #' 20 | #' @examples 21 | #' 22 | #' types.castTime(format = "default", value = '06:00:00') 23 | #' 24 | 25 | types.castTime <- function(format="%H:%M:%S", value) { 26 | 27 | if (!lubridate::is.instant(value)) { 28 | 29 | if (!is.character(value)) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 30 | 31 | value <- tryCatch( { 32 | 33 | if (format == "%H:%M:%S" | format == "default" | format == "any") { 34 | format <- "%H:%M:%S" 35 | value <- format(value, format = format) 36 | 37 | value <- as.POSIXlt(value, format = format) 38 | #value = strftime(value, format = format ) 39 | 40 | } else if (startsWith(format,"fmt:")) { 41 | 42 | message(config::get("WARNING", file = system.file("config/config.yml", package = "tableschema.r"))) 43 | #warning("Format ",format," is deprecated.\nPlease use ",unlist(strsplit(format,":"))[2]," without 'fmt:' prefix.", call. = FALSE) 44 | 45 | format <- trimws(gsub("fmt:","",format),which = "both") 46 | 47 | value <- as.POSIXlt(value, format = format) 48 | #value = strftime(value, format = format) 49 | 50 | } else if ( format != "%H:%M:%S" & !startsWith(format,"fmt:") ) { 51 | format <- "%H:%M:%S" 52 | value <- format(value, format = format) 53 | 54 | value <- as.POSIXlt(value, format = format) 55 | #value = strftime(value, format = format) 56 | } 57 | 58 | if ( !lubridate::is.POSIXlt(strptime(value, format = format)) || is.na(value) ) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 59 | 60 | value <- strftime(as.POSIXlt(value, format = format), format = format) 61 | 62 | }, 63 | warning = function(w) { 64 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 65 | }, 66 | error = function(e) { 67 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 68 | }, 69 | finally = {}) 70 | } 71 | 72 | return(value) 73 | } 74 | 75 | -------------------------------------------------------------------------------- /R/types.castYear.R: -------------------------------------------------------------------------------- 1 | #' @title Cast year 2 | #' @description Cast year. A calendar year as per \href{https://www.w3.org/TR/xmlschema-2/#gYear}{XMLSchema gYear}. 3 | #' Usual lexical representation is: YYYY. 4 | #' @param format no options (other than the default) 5 | #' @param value year to cast 6 | #' @rdname types.castYear 7 | #' @export 8 | #' 9 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#year}{Types and formats specifications} 10 | #' 11 | #' @examples 12 | #' 13 | #' types.castYear(format = "default", value = 2000) 14 | #' 15 | #' types.castYear(format = "default", value = "2010") 16 | #' 17 | 18 | types.castYear <- function(format, value) { 19 | 20 | if (!is_integer(value)) { 21 | 22 | if (!is.character(value)) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 23 | 24 | if (length(value) > 1) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 25 | 26 | if (nchar(value) != 4 | isTRUE(grepl('[a-zA-Z]', value))) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 27 | 28 | tryCatch({ 29 | 30 | result <- as.integer(value) 31 | 32 | if (is.na(result) | 33 | is.nan(result) | 34 | as.character(result) != value) { 35 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 36 | } 37 | 38 | value <- result 39 | }, 40 | 41 | warning = function(w) { 42 | message(config::get("WARNING", file = system.file("config/config.yml", package = "tableschema.r"))) 43 | }, 44 | 45 | error = function(e) { 46 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 47 | }, 48 | finally = {}) 49 | } 50 | 51 | if (is.na(value) | value < 0 | value > 9999) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 52 | 53 | return(value) 54 | } 55 | -------------------------------------------------------------------------------- /R/types.castYearmonth.R: -------------------------------------------------------------------------------- 1 | #' @title Cast a specific month in a specific year 2 | #' @description Cast a specific month in a specific year as per \href{https://www.w3.org/TR/xmlschema-2/#gYearMonth}{XMLSchema gYearMonth}. 3 | #' Usual lexical representation is: YYYY-MM. 4 | #' @param format no options (other than the default) 5 | #' @param value list or string with yearmonth to cast 6 | #' @rdname types.castYearmonth 7 | #' @export 8 | #' 9 | #' @seealso \href{https://specs.frictionlessdata.io//table-schema/#yearmonth}{Types and formats specifications} 10 | #' 11 | #' @examples 12 | #' 13 | #' types.castYearmonth(format = "default", value = list(2000, 10)) 14 | #' 15 | #' types.castYearmonth(format = "default", value = "2018-11") 16 | #' 17 | 18 | types.castYearmonth <- function(format, value) { 19 | 20 | if (isTRUE(is_empty(value))) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 21 | 22 | if (any(is.array(value) | is.list(value))) { 23 | 24 | if (length(value) != 2 | any(unlist(value) < 0) | unlist(value)[2] > 12 ) { 25 | 26 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 27 | } 28 | 29 | } else if (is.character(value) & !isTRUE(grepl('[a-zA-Z]', value)) ) { 30 | 31 | tryCatch({ 32 | 33 | splitter <- if (length(strsplit(value, split = "/")[[1]]) == 1) "-" else "/" 34 | 35 | value <- as.list(unlist(strsplit(value, split = splitter))) 36 | 37 | if (nchar(as.integer(value[[1]])) != 4 ) { 38 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 39 | } 40 | #names(value) = c("year", "month") 41 | 42 | year <- as.integer(value[[1]]) 43 | 44 | month <- as.integer(value[[2]]) 45 | 46 | #if (!year | !month) return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 47 | 48 | if (month < 1 | month > 12) { 49 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 50 | } 51 | #value = list(year = year, month = month) 52 | value <- list(year, month) 53 | 54 | }, 55 | warning = function(w) { 56 | 57 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 58 | 59 | }, 60 | 61 | error = function(e) { 62 | 63 | return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 64 | 65 | }, 66 | 67 | finally = { 68 | 69 | }) 70 | 71 | } else return(config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 72 | 73 | return(value) 74 | } 75 | -------------------------------------------------------------------------------- /R/validate.R: -------------------------------------------------------------------------------- 1 | #' validate descriptor 2 | #' @description Validates whether a schema is a validate Table Schema accordingly to the specifications. 3 | #' It does not validate data against a schema. 4 | #' @param descriptor schema descriptor, one of: 5 | #' \itemize{ 6 | #' \item string with the local CSV file (path) 7 | #' \item string with the remote CSV file (url) 8 | #' \item list object 9 | #' } 10 | #' @return \code{TRUE} on valid 11 | #' @rdname validate 12 | #' @export 13 | #' 14 | 15 | # Module API 16 | 17 | validate <- function(descriptor) { 18 | 19 | # https://github.com/frictionlessdata/tableschema-js#infer 20 | def <- Schema.load(descriptor) 21 | schema <- future::value(def) 22 | return(list(valid = schema$valid, errors = schema$errors)) 23 | } 24 | -------------------------------------------------------------------------------- /R/writable.R: -------------------------------------------------------------------------------- 1 | #' Writeable class 2 | #' @description Writable streams class 3 | #' @docType class 4 | #' @importFrom R6 R6Class 5 | #' @export 6 | #' @include constraints.R 7 | #' @include tableschemaerror.R 8 | #' @include profile.R 9 | #' @keywords data 10 | #' @return Object of \code{\link{R6Class}} . 11 | #' @format \code{\link{R6Class}} object. 12 | #' 13 | 14 | Writeable <- R6Class( 15 | "Writeable", 16 | 17 | public = list( 18 | initialize = function(options = list()) { 19 | 20 | private$drain_() 21 | }, 22 | 23 | write = function(chunk){ 24 | private$buffer_ <- rlist::list.append(private$buffer_, chunk) 25 | }, 26 | 27 | 28 | read = function(size = NULL) { 29 | 30 | }, 31 | pipe = function(destination, options = list()) { 32 | 33 | 34 | }, 35 | unpipe = function(destination) { 36 | 37 | }, 38 | pause = function() { 39 | 40 | }, 41 | resume = function() { 42 | 43 | }, 44 | setEncoding = function() { 45 | 46 | }, 47 | isPaused = function() { 48 | 49 | }, 50 | unshift = function(chunk) { 51 | }, 52 | destroy = function() { 53 | 54 | }, 55 | 56 | push = function(chunk, encoding) { 57 | 58 | }, 59 | 60 | on.drain = NULL, 61 | 62 | onClose = function(handler, unsubscribe = FALSE) { 63 | private$subscribeUnsubscribe_('close', handler, unsubscribe) 64 | }, 65 | 66 | onData = function(handler, unsubscribe = FALSE) { 67 | private$subscribeUnsubscribe_('data', handler, unsubscribe) 68 | }, 69 | 70 | onEnd = function(handler, unsubscribe = FALSE) { 71 | private$subscribeUnsubscribe_('end', handler, unsubscribe) 72 | }, 73 | 74 | onError = function(handler, unsubscribe = FALSE) { 75 | private$subscribeUnsubscribe_('error', handler, unsubscribe) 76 | }, 77 | 78 | onReadable = function(handler, unsubscribe = FALSE) { 79 | private$subscribeUnsubscribe_('readable', handler, unsubscribe) 80 | } 81 | 82 | ), 83 | active = list( 84 | destroyed = function(value) { 85 | } 86 | ), 87 | 88 | private = list( 89 | encoding_ = NULL, 90 | objectMode_ = FALSE, 91 | drain_ = function() { 92 | future::future( { 93 | while (TRUE) { 94 | if (length(private$buffer_) > 0) { 95 | chunk <- private$buffer_[[1]] 96 | private$buffer_ <- rlist::list.remove(private$buffer_, 1) 97 | print(chunk) 98 | } 99 | else{ 100 | self$on.drain() 101 | } 102 | } 103 | }) 104 | }, 105 | destroy_ = function() { 106 | 107 | }, 108 | buffer_ = list(), 109 | readable_ = TRUE, 110 | paused_ = TRUE, 111 | pipeDestinations_ = list(), 112 | 113 | eventHandlers_ = list( 114 | 'close' = list(), 115 | data = list(), 116 | end = list(), 117 | error = list(), 118 | readable = list() 119 | ), 120 | 121 | emit_ = function(event, arguments = list()) { 122 | for (handler in private$eventHandlers_[[event]]) { 123 | handler(arguments) 124 | } 125 | }, 126 | subscribeUnsubscribe_ = function(event, handler, unsubscribe = FALSE) { 127 | if (!unsubscribe) { 128 | rlist::list.append(private$eventHandlers_[[event]], handler) 129 | } 130 | else { 131 | rlist::list.remove(private$eventHandlers_[[event]], function(eventHandler) { 132 | return(identical(eventHandler, handler)) 133 | }) 134 | } 135 | } 136 | ) 137 | ) 138 | -------------------------------------------------------------------------------- /docs/Ffrictionless.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frictionlessdata/tableschema-r/f5f40bdfca2044753fbbd0f2aeebd1b5e4041181/docs/Ffrictionless.png -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /docs/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /docs/okgr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frictionlessdata/tableschema-r/f5f40bdfca2044753fbbd0f2aeebd1b5e4041181/docs/okgr.png -------------------------------------------------------------------------------- /docs/oklabs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frictionlessdata/tableschema-r/f5f40bdfca2044753fbbd0f2aeebd1b5e4041181/docs/oklabs.png -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | /* http://gregfranko.com/blog/jquery-best-practices/ */ 2 | (function($) { 3 | $(function() { 4 | 5 | $('.navbar-fixed-top').headroom(); 6 | 7 | $('body').css('padding-top', $('.navbar').height() + 10); 8 | $(window).resize(function(){ 9 | $('body').css('padding-top', $('.navbar').height() + 10); 10 | }); 11 | 12 | $('body').scrollspy({ 13 | target: '#sidebar', 14 | offset: 60 15 | }); 16 | 17 | $('[data-toggle="tooltip"]').tooltip(); 18 | 19 | var cur_path = paths(location.pathname); 20 | var links = $("#navbar ul li a"); 21 | var max_length = -1; 22 | var pos = -1; 23 | for (var i = 0; i < links.length; i++) { 24 | if (links[i].getAttribute("href") === "#") 25 | continue; 26 | // Ignore external links 27 | if (links[i].host !== location.host) 28 | continue; 29 | 30 | var nav_path = paths(links[i].pathname); 31 | 32 | var length = prefix_length(nav_path, cur_path); 33 | if (length > max_length) { 34 | max_length = length; 35 | pos = i; 36 | } 37 | } 38 | 39 | // Add class to parent
  • , and enclosing
  • if in dropdown 40 | if (pos >= 0) { 41 | var menu_anchor = $(links[pos]); 42 | menu_anchor.parent().addClass("active"); 43 | menu_anchor.closest("li.dropdown").addClass("active"); 44 | } 45 | }); 46 | 47 | function paths(pathname) { 48 | var pieces = pathname.split("/"); 49 | pieces.shift(); // always starts with / 50 | 51 | var end = pieces[pieces.length - 1]; 52 | if (end === "index.html" || end === "") 53 | pieces.pop(); 54 | return(pieces); 55 | } 56 | 57 | // Returns -1 if not found 58 | function prefix_length(needle, haystack) { 59 | if (needle.length > haystack.length) 60 | return(-1); 61 | 62 | // Special case for length-0 haystack, since for loop won't run 63 | if (haystack.length === 0) { 64 | return(needle.length === 0 ? 0 : -1); 65 | } 66 | 67 | for (var i = 0; i < haystack.length; i++) { 68 | if (needle[i] != haystack[i]) 69 | return(i); 70 | } 71 | 72 | return(haystack.length); 73 | } 74 | 75 | /* Clipboard --------------------------*/ 76 | 77 | function changeTooltipMessage(element, msg) { 78 | var tooltipOriginalTitle=element.getAttribute('data-original-title'); 79 | element.setAttribute('data-original-title', msg); 80 | $(element).tooltip('show'); 81 | element.setAttribute('data-original-title', tooltipOriginalTitle); 82 | } 83 | 84 | if(ClipboardJS.isSupported()) { 85 | $(document).ready(function() { 86 | var copyButton = ""; 87 | 88 | $(".examples, div.sourceCode").addClass("hasCopyButton"); 89 | 90 | // Insert copy buttons: 91 | $(copyButton).prependTo(".hasCopyButton"); 92 | 93 | // Initialize tooltips: 94 | $('.btn-copy-ex').tooltip({container: 'body'}); 95 | 96 | // Initialize clipboard: 97 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { 98 | text: function(trigger) { 99 | return trigger.parentNode.textContent; 100 | } 101 | }); 102 | 103 | clipboardBtnCopies.on('success', function(e) { 104 | changeTooltipMessage(e.trigger, 'Copied!'); 105 | e.clearSelection(); 106 | }); 107 | 108 | clipboardBtnCopies.on('error', function() { 109 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 110 | }); 111 | }); 112 | } 113 | })(window.jQuery || window.$) 114 | -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: 2.7.2 2 | pkgdown: 1.4.1 3 | pkgdown_sha: ~ 4 | articles: [] 5 | 6 | -------------------------------------------------------------------------------- /frictionlessdata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frictionlessdata/tableschema-r/f5f40bdfca2044753fbbd0f2aeebd1b5e4041181/frictionlessdata.png -------------------------------------------------------------------------------- /inst/config/config.yml: -------------------------------------------------------------------------------- 1 | default: 2 | ERROR: 'tableschema.error' 3 | WARNING: 'tableschema.warning' 4 | DEFAULT_FIELD_TYPE: 'string' 5 | DEFAULT_FIELD_FORMAT: 'default' 6 | DEFAULT_MISSING_VALUES: [''] 7 | -------------------------------------------------------------------------------- /inst/extdata/data.csv: -------------------------------------------------------------------------------- 1 | city,location 2 | london,"51.50 -0.11" 3 | paris,"48.85 2.30" 4 | rome,N/A 5 | -------------------------------------------------------------------------------- /inst/extdata/data_delim.csv: -------------------------------------------------------------------------------- 1 | id;name 2 | 1;"abc, ab" 3 | -------------------------------------------------------------------------------- /inst/extdata/data_delim2.csv: -------------------------------------------------------------------------------- 1 | id,name 2 | 1,"abc, ab" 3 | 2,"cba, ba" 4 | -------------------------------------------------------------------------------- /inst/extdata/data_infer.csv: -------------------------------------------------------------------------------- 1 | id,age,name 2 | 1,39,Paul 3 | 2,23,Jimmy 4 | 3,36,Jane 5 | 4,28,Judy 6 | -------------------------------------------------------------------------------- /inst/extdata/data_infer_formats.csv: -------------------------------------------------------------------------------- 1 | id,capital,url 2 | 1,39.00$,http://www.test.com 3 | 2,23.00$,http://www.test.de 4 | 3,36.00$,http://www.test.uk 5 | 4,28.00$,http://www.test.co.il -------------------------------------------------------------------------------- /inst/extdata/data_infer_row_limit.csv: -------------------------------------------------------------------------------- 1 | id,age,name 2 | 1,39,Paul 3 | 2,23,Jimmy 4 | 3,36,Jane 5 | 4,28,Judy 6 | qwerty,nineteen,Rose 7 | werty,nineteen,Red 8 | erty,nineteen,Rotem 9 | rty,nineteen,Ruth 10 | ty,nineteen,Amber 11 | y,nineteen,Angel 12 | _,nineteen,Angie 13 | -------------------------------------------------------------------------------- /inst/extdata/data_infer_utf8.csv: -------------------------------------------------------------------------------- 1 | id,age,name 2 | 1,39,Paul 3 | 2,23,Jimmy 4 | 3,36,Jane 5 | 4,28,Judy 6 | 5,37,Iñtërnâtiônàlizætiøn 7 | -------------------------------------------------------------------------------- /inst/extdata/data_parse_options_default.csv: -------------------------------------------------------------------------------- 1 | id,age,name 2 | 1,39, Paul 3 | 2,23,Jimmy 4 | 3,36,Jane 5 | 4,28,Judy 6 | -------------------------------------------------------------------------------- /inst/extdata/data_parse_options_delimiter.csv: -------------------------------------------------------------------------------- 1 | id;age;name 2 | 1;39;Paul 3 | 2;23;Jimmy 4 | 3;36;Jane 5 | 4;28;Judy 6 | -------------------------------------------------------------------------------- /inst/extdata/jsonchar.json: -------------------------------------------------------------------------------- 1 | "{\"fields\":[{\"name\":\"id\",\"type\":\"string\",\"constraints\":{\"required\":true},\"format\":\"default\"},{\"name\":\"height\",\"type\":\"number\",\"format\":\"default\"},{\"name\":\"age\",\"type\":\"integer\",\"format\":\"default\"},{\"name\":\"name\",\"type\":\"string\",\"constraints\":{\"required\":true},\"format\":\"default\"},{\"name\":\"occupation\",\"type\":\"string\",\"format\":\"default\"}],\"missingValues\":[\"\"]}" 2 | 3 | -------------------------------------------------------------------------------- /inst/extdata/latin1.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frictionlessdata/tableschema-r/f5f40bdfca2044753fbbd0f2aeebd1b5e4041181/inst/extdata/latin1.csv -------------------------------------------------------------------------------- /inst/extdata/mathematics.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": [ 3 | { 4 | "description": "Total Number of Grades", 5 | "name": "Grade", 6 | "type": "string" 7 | }, 8 | { 9 | "description": "Grade Awarding Year", 10 | "format": "any", 11 | "name": "Year", 12 | "type": "date" 13 | }, 14 | { 15 | "description": "Education Category (General, Special)", 16 | "name": "Category", 17 | "type": "string" 18 | }, 19 | { 20 | "constraints": { 21 | "level": "Ratio" 22 | }, 23 | "description": "Total number of tested", 24 | "name": "Number_Tested", 25 | "type": "integer" 26 | }, 27 | { 28 | "constraints": { 29 | "level": "Ratio" 30 | }, 31 | "description": "Mean of Scale Core", 32 | "name": "Mean_Scale_Score", 33 | "type": "integer" 34 | }, 35 | { 36 | "constraints": { 37 | "level": "Ratio" 38 | }, 39 | "description": "Score of Level 1", 40 | "name": "Number_Level_1", 41 | "type": "integer" 42 | }, 43 | { 44 | "constraints": { 45 | "level": "Ratio" 46 | }, 47 | "description": "Percentage of Level 1", 48 | "name": "Percentage_Level_1", 49 | "type": "number" 50 | }, 51 | { 52 | "constraints": { 53 | "level": "Ratio" 54 | }, 55 | "description": "Score of Level 2", 56 | "name": "Number_Level_2", 57 | "type": "integer" 58 | }, 59 | { 60 | "constraints": { 61 | "level": "Ratio" 62 | }, 63 | "description": "Percentage of Level 2", 64 | "name": "Percentage_Level_2", 65 | "type": "number" 66 | }, 67 | { 68 | "constraints": { 69 | "level": "Ratio" 70 | }, 71 | "description": "Score of Level 3", 72 | "name": "Number_Level_3", 73 | "type": "integer" 74 | }, 75 | { 76 | "constraints": { 77 | "level": "Ratio" 78 | }, 79 | "description": "Percentage of Level 3", 80 | "name": "Percentage_Level_3", 81 | "type": "number" 82 | }, 83 | { 84 | "constraints": { 85 | "level": "Ratio" 86 | }, 87 | "description": "Score of Level 4", 88 | "name": "Number_Level_4", 89 | "type": "integer" 90 | }, 91 | { 92 | "constraints": { 93 | "level": "Ratio" 94 | }, 95 | "description": "Percentage of Level 4", 96 | "name": "Percentage_Level_4", 97 | "type": "number" 98 | } 99 | ] 100 | } -------------------------------------------------------------------------------- /inst/extdata/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": [ 3 | { 4 | "name": "id", 5 | "type": "string", 6 | "constraints": { 7 | "required": true 8 | }, 9 | "format": "default" 10 | }, 11 | { 12 | "name": "height", 13 | "type": "number", 14 | "format": "default" 15 | }, 16 | { 17 | "name": "age", 18 | "type": "integer", 19 | "format": "default" 20 | }, 21 | { 22 | "name": "name", 23 | "type": "string", 24 | "constraints": { 25 | "required": true 26 | }, 27 | "format": "default" 28 | }, 29 | { 30 | "name": "occupation", 31 | "type": "string", 32 | "format": "default" 33 | } 34 | ], 35 | "missingValues": [ 36 | "" 37 | ] 38 | } 39 | 40 | -------------------------------------------------------------------------------- /inst/extdata/schema2.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": [{ 3 | "name": "id", 4 | "title": "", 5 | "description": "", 6 | "type": "integer", 7 | "format": "default" 8 | }, 9 | { 10 | "name": "capital", 11 | "title": "", 12 | "description": "", 13 | "type": "number" 14 | }, 15 | { 16 | "name": "url", 17 | "title": "", 18 | "description": "", 19 | "type": "string" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /inst/extdata/schema_valid_full.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": [ 3 | { 4 | "name": "first_name", 5 | "title": "First Name", 6 | "type": "string", 7 | "description": "The first name of the person" 8 | }, 9 | { 10 | "name": "last_name", 11 | "title": "Last Name", 12 | "type": "string", 13 | "description": "The last name of the person" 14 | }, 15 | { 16 | "name": "gender", 17 | "title": "Gender", 18 | "type": "string", 19 | "description": "The gender of the person." 20 | }, 21 | { 22 | "name": "age", 23 | "title": "Age", 24 | "type": "integer", 25 | "description": "The age of this person." 26 | }, 27 | { 28 | "name": "period_employed", 29 | "title": "Period Employed", 30 | "type": "number", 31 | "description": "The period of employment, in years (eg: 2.6 Y)." 32 | }, 33 | { 34 | "name": "employment_start", 35 | "title": "Employment Start", 36 | "type": "date", 37 | "description": "The date this person started employment." 38 | }, 39 | { 40 | "name": "daily_start", 41 | "title": "Daily Start", 42 | "type": "time", 43 | "description": "Usual start time for this person." 44 | }, 45 | { 46 | "name": "daily_end", 47 | "title": "Daily End", 48 | "type": "time", 49 | "description": "Usual end time for this person." 50 | }, 51 | { 52 | "name": "is_management", 53 | "title": "Is Management", 54 | "type": "boolean", 55 | "description": "Is this person part of upper management." 56 | }, 57 | { 58 | "name": "photo", 59 | "title": "Photo", 60 | "type": "string", 61 | "format": "binary", 62 | "description": "A photo of this person." 63 | }, 64 | { 65 | "name": "interests", 66 | "title": "Interests", 67 | "type": "array", 68 | "description": "Declared interests of this person (work-related)." 69 | }, 70 | { 71 | "name": "home_location", 72 | "title": "Home Location", 73 | "type": "geopoint", 74 | "description": "A geopoint for this person's home address." 75 | }, 76 | { 77 | "name": "position_title", 78 | "title": "Position Title", 79 | "type": "string", 80 | "description": "This person's position in the company." 81 | }, 82 | { 83 | "name": "extra", 84 | "title": "Extra", 85 | "type": "object", 86 | "description": "Extra information about this person." 87 | }, 88 | { 89 | "name": "notes", 90 | "title": "Notes", 91 | "type": "any", 92 | "description": "Add any relevant notes for HR." 93 | } 94 | ], 95 | "primaryKey": [ 96 | "first_name", 97 | "last_name", 98 | "period_employed", 99 | "home_location" 100 | ], 101 | "foreignKeys": [ 102 | { 103 | "fields": ["position_title"], 104 | "reference": { 105 | "resource": "positions", 106 | "fields": ["name"] 107 | } 108 | } 109 | ] 110 | } 111 | -------------------------------------------------------------------------------- /man/Constraints.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/constraints.R 3 | \docType{class} 4 | \name{Constraints} 5 | \alias{Constraints} 6 | \title{Constraints class} 7 | \format{ 8 | \code{\link{R6Class}} object. 9 | } 10 | \value{ 11 | Object of \code{\link{R6Class}} . 12 | } 13 | \description{ 14 | R6 class with constraints. 15 | 16 | The constraints property on Table Schema Fields can be used by consumers to list constraints for 17 | validating field values. For example, validating the data in a Tabular Data Resource against 18 | its Table Schema; or as a means to validate data being collected or updated via a data entry interface. 19 | 20 | All constraints \code{MUST} be tested against the logical representation of data, and the physical 21 | representation of constraint values \code{MAY} be primitive types as possible in JSON, 22 | or represented as strings that are castable with the type and format rules of the field. 23 | } 24 | \section{Fields}{ 25 | 26 | \describe{ 27 | \item{\code{constraints}}{see Section See Also} 28 | }} 29 | 30 | \seealso{ 31 | \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications}, 32 | \code{\link{constraints.checkEnum}}, 33 | \code{\link{constraints.checkMaximum}}, 34 | \code{\link{constraints.checkMaxLength}}, 35 | \code{\link{constraints.checkMinimum}}, 36 | \code{\link{constraints.checkMinLength}}, 37 | \code{\link{constraints.checkPattern}}, 38 | \code{\link{constraints.checkRequired}}, 39 | \code{\link{constraints.checkUnique}} 40 | } 41 | \keyword{data} 42 | -------------------------------------------------------------------------------- /man/DEFAULT_DECIMAL_CHAR.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castNumber.R 3 | \docType{data} 4 | \name{DEFAULT_DECIMAL_CHAR} 5 | \alias{DEFAULT_DECIMAL_CHAR} 6 | \title{default decimal char} 7 | \format{ 8 | An object of class \code{character} of length 1. 9 | } 10 | \usage{ 11 | DEFAULT_DECIMAL_CHAR 12 | } 13 | \description{ 14 | default decimal char 15 | } 16 | \keyword{datasets} 17 | -------------------------------------------------------------------------------- /man/DEFAULT_GROUP_CHAR.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castNumber.R 3 | \docType{data} 4 | \name{DEFAULT_GROUP_CHAR} 5 | \alias{DEFAULT_GROUP_CHAR} 6 | \title{default group char} 7 | \format{ 8 | An object of class \code{character} of length 1. 9 | } 10 | \usage{ 11 | DEFAULT_GROUP_CHAR 12 | } 13 | \description{ 14 | default group char 15 | } 16 | \keyword{datasets} 17 | -------------------------------------------------------------------------------- /man/FALSE_VALUES.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castBoolean.R 3 | \docType{data} 4 | \name{FALSE_VALUES} 5 | \alias{FALSE_VALUES} 6 | \title{default false values} 7 | \format{ 8 | An object of class \code{character} of length 4. 9 | } 10 | \usage{ 11 | FALSE_VALUES 12 | } 13 | \description{ 14 | default false values 15 | } 16 | \keyword{datasets} 17 | -------------------------------------------------------------------------------- /man/Profile.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/profile.R 3 | \docType{class} 4 | \name{Profile} 5 | \alias{Profile} 6 | \title{Profile class} 7 | \format{ 8 | \code{\link{R6Class}} object. 9 | } 10 | \usage{ 11 | # Profile$load(profile) 12 | } 13 | \arguments{ 14 | \item{profile}{String: the name of a profile from the registry or a URL pointing to a JSON Schema.} 15 | } 16 | \value{ 17 | Object of class \code{\link{R6Class}}. 18 | } 19 | \description{ 20 | Class to represent a JSON Schema profile from the \href{https://specs.frictionlessdata.io/schemas/registry.json}{Profiles Registry}. 21 | } 22 | \section{Methods}{ 23 | 24 | \describe{ 25 | \item{\code{Profile$new(descriptor = descriptor)}}{Use \code{Profile$load} to instantiate a \code{Profile} class.} 26 | 27 | \item{\code{validate(descriptor)}}{Validate a tabular data package descriptor against the \code{Profile}. 28 | \describe{ 29 | \item{\code{descriptor}}{The dereferenced tabular data package descriptor to validate.} 30 | \item{Return value}{Returns \code{TRUE} if the descriptor is valid; otherwise returns \code{FALSE} with an error message.} 31 | } 32 | } 33 | } 34 | } 35 | 36 | \section{Properties}{ 37 | 38 | \describe{ 39 | \item{\code{name}}{Returns the profile name, if available.} 40 | \item{\code{jsonschema}}{Returns the contents of the profile's JSON Schema.} 41 | } 42 | } 43 | 44 | \seealso{ 45 | \href{https://specs.frictionlessdata.io//profiles/}{Profile Specifications} 46 | } 47 | \keyword{data} 48 | -------------------------------------------------------------------------------- /man/Profile.load.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/profile.R 3 | \name{Profile.load} 4 | \alias{Profile.load} 5 | \title{Instantiate \code{Profile} class} 6 | \usage{ 7 | Profile.load(profile) 8 | } 9 | \arguments{ 10 | \item{profile}{string profile name in registry or URL to JSON Schema} 11 | } 12 | \value{ 13 | \code{\link{Profile}} class object 14 | } 15 | \description{ 16 | Constuctor to instantiate \code{\link{Profile}} class. 17 | } 18 | -------------------------------------------------------------------------------- /man/Readable.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/readable.R 3 | \docType{class} 4 | \name{Readable} 5 | \alias{Readable} 6 | \title{Readable class} 7 | \format{ 8 | \code{\link{R6Class}} object. 9 | } 10 | \value{ 11 | Object of \code{\link{R6Class}}. 12 | } 13 | \description{ 14 | Readable class that allows typed access to its members 15 | } 16 | \keyword{data} 17 | -------------------------------------------------------------------------------- /man/ReadableArray.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/readable.array.R 3 | \docType{class} 4 | \name{ReadableArray} 5 | \alias{ReadableArray} 6 | \title{ReadableArray class} 7 | \format{ 8 | \code{\link{R6Class}} object. 9 | } 10 | \value{ 11 | Object of \code{\link{R6Class}} . 12 | } 13 | \description{ 14 | Readable Array class 15 | } 16 | \keyword{data} 17 | -------------------------------------------------------------------------------- /man/ReadableConnection.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/readable.connection.R 3 | \docType{class} 4 | \name{ReadableConnection} 5 | \alias{ReadableConnection} 6 | \title{ReadableConnection class} 7 | \format{ 8 | \code{\link{R6Class}} object. 9 | } 10 | \value{ 11 | Object of \code{\link{R6Class}} . 12 | } 13 | \description{ 14 | Readable connection class 15 | } 16 | \keyword{data} 17 | -------------------------------------------------------------------------------- /man/TRUE_VALUES.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castBoolean.R 3 | \docType{data} 4 | \name{TRUE_VALUES} 5 | \alias{TRUE_VALUES} 6 | \title{default true values} 7 | \format{ 8 | An object of class \code{character} of length 4. 9 | } 10 | \usage{ 11 | TRUE_VALUES 12 | } 13 | \description{ 14 | default true values 15 | } 16 | \keyword{datasets} 17 | -------------------------------------------------------------------------------- /man/TableSchemaError.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tableschemaerror.R 3 | \docType{class} 4 | \name{TableSchemaError} 5 | \alias{TableSchemaError} 6 | \title{TableSchemaError class} 7 | \format{ 8 | \code{\link{R6Class}} object. 9 | } 10 | \arguments{ 11 | \item{message}{message} 12 | 13 | \item{error}{error} 14 | } 15 | \value{ 16 | Object of \code{\link{R6Class}} . 17 | } 18 | \description{ 19 | Error class for Table Schema 20 | } 21 | \section{Fields}{ 22 | 23 | \describe{ 24 | \item{\code{message}}{} 25 | 26 | \item{\code{error}}{} 27 | }} 28 | 29 | \keyword{data} 30 | -------------------------------------------------------------------------------- /man/Types.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.R 3 | \docType{class} 4 | \name{Types} 5 | \alias{Types} 6 | \title{Types class} 7 | \format{ 8 | \code{\link{R6Class}} object. 9 | } 10 | \value{ 11 | Object of \code{\link{R6Class}} . 12 | } 13 | \description{ 14 | R6 class with Types and Formats. 15 | 16 | \code{type} and \code{format} properties are used to give the type of the field (string, number etc) - 17 | see \href{https://specs.frictionlessdata.io//table-schema/#types-and-formats}{types and formats} for more details. 18 | If type is not provided a consumer should assume a type of "string". 19 | 20 | A field's \code{type} property is a string indicating the type of this field. 21 | 22 | A field's \code{format} property is a string, indicating a format for the field type. 23 | 24 | Both \code{type} and format are optional: in a field descriptor, the absence of a \code{type} property indicates that 25 | the field is of the type "string", and the absence of a \code{format} property indicates that the field's type \code{format} is "default". 26 | 27 | Types are based on the \href{https://datatracker.ietf.org/doc/html/draft-zyp-json-schema-03#section-5.1}{type set of json-schema} 28 | with some additions and minor modifications (cf other type lists include those in 29 | \href{http://www.elasticsearch.org/guide/reference/mapping/}{Elasticsearch types}). 30 | } 31 | \section{Fields}{ 32 | 33 | \describe{ 34 | \item{\code{casts}}{see Section See also} 35 | }} 36 | 37 | \seealso{ 38 | \href{https://specs.frictionlessdata.io//table-schema/#types-and-formats}{Types and formats specifications}, 39 | \code{\link{types.castAny}}, 40 | \code{\link{types.castBoolean}}, 41 | \code{\link{types.castDate}}, 42 | \code{\link{types.castDatetime}}, 43 | \code{\link{types.castDuration}}, 44 | \code{\link{types.castGeojson}}, 45 | \code{\link{types.castGeopoint}}, 46 | \code{\link{types.castInteger}}, 47 | \code{\link{types.castList}}, 48 | \code{\link{types.castNumber}}, 49 | \code{\link{types.castObject}}, 50 | \code{\link{types.castString}}, 51 | \code{\link{types.castTime}}, 52 | \code{\link{types.castYear}}, 53 | \code{\link{types.castYearmonth}}, 54 | \code{\link{types.castArray}} 55 | } 56 | \keyword{data} 57 | -------------------------------------------------------------------------------- /man/Writeable.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/writable.R 3 | \docType{class} 4 | \name{Writeable} 5 | \alias{Writeable} 6 | \title{Writeable class} 7 | \format{ 8 | \code{\link{R6Class}} object. 9 | } 10 | \value{ 11 | Object of \code{\link{R6Class}} . 12 | } 13 | \description{ 14 | Writable streams class 15 | } 16 | \keyword{data} 17 | -------------------------------------------------------------------------------- /man/constraints.checkEnum.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/constraints.checkEnum.R 3 | \name{constraints.checkEnum} 4 | \alias{constraints.checkEnum} 5 | \title{Check Enum} 6 | \usage{ 7 | constraints.checkEnum(constraint, value) 8 | } 9 | \arguments{ 10 | \item{constraint}{numeric list,matrix or vector with the constraint values} 11 | 12 | \item{value}{numeric value to meet the constraint} 13 | } 14 | \value{ 15 | TRUE if value meets the constraint 16 | } 17 | \description{ 18 | Check if the value is exactly match a constraint. 19 | } 20 | \examples{ 21 | 22 | constraints.checkEnum(constraint = list(1, 2), value = 1) 23 | 24 | constraints.checkEnum(constraint = list(1, 2), value = 3) 25 | } 26 | \seealso{ 27 | \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications} 28 | } 29 | -------------------------------------------------------------------------------- /man/constraints.checkMaxLength.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/constraints.checkMaxLength.R 3 | \name{constraints.checkMaxLength} 4 | \alias{constraints.checkMaxLength} 5 | \title{Check if maximum character length constraint is met} 6 | \usage{ 7 | constraints.checkMaxLength(constraint, value) 8 | } 9 | \arguments{ 10 | \item{constraint}{numeric constraint, maximum character length} 11 | 12 | \item{value}{character to meet the constraint} 13 | } 14 | \value{ 15 | TRUE if character length is equal to or less than the constraint 16 | } 17 | \description{ 18 | Specify the maximum length of a character 19 | } 20 | \examples{ 21 | 22 | constraints.checkMaxLength(constraint = list(2), value = "hi") 23 | 24 | constraints.checkMaxLength(constraint = 2, value = "hello") 25 | } 26 | \seealso{ 27 | \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications} 28 | } 29 | -------------------------------------------------------------------------------- /man/constraints.checkMaximum.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/constraints.checkMaximum.R 3 | \name{constraints.checkMaximum} 4 | \alias{constraints.checkMaximum} 5 | \title{Check if maximum constraint is met} 6 | \usage{ 7 | constraints.checkMaximum(constraint, value) 8 | } 9 | \arguments{ 10 | \item{constraint}{numeric constraint value} 11 | 12 | \item{value}{numeric value to meet the constraint} 13 | } 14 | \value{ 15 | TRUE if value is equal to or less than the constraint 16 | } 17 | \description{ 18 | Specifies a maximum value for a field. This is different to \code{maxLength} which checks the number of items in the value. 19 | A maximum value constraint checks whether a field value is equal to or less than the specified value. 20 | The range checking depends on the type of the field. E.g. an integer field may have a maximum value of 100. 21 | If a maximum value constraint is specified then the field descriptor \code{MUST} contain a type key. 22 | } 23 | \examples{ 24 | 25 | constraints.checkMaximum(constraint = list(2), value = 1) 26 | 27 | constraints.checkMaximum(constraint = 2, value = 3) 28 | 29 | } 30 | \seealso{ 31 | \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications} 32 | } 33 | -------------------------------------------------------------------------------- /man/constraints.checkMinLength.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/constraints.checkMinLength.R 3 | \name{constraints.checkMinLength} 4 | \alias{constraints.checkMinLength} 5 | \title{Check if minimum character length constraint is met} 6 | \usage{ 7 | constraints.checkMinLength(constraint, value) 8 | } 9 | \arguments{ 10 | \item{constraint}{numeric constraint, minimum character length} 11 | 12 | \item{value}{character to meet the constraint} 13 | } 14 | \value{ 15 | TRUE if character length is equal to or greater than the constraint 16 | } 17 | \description{ 18 | Specify the minimum length of a character 19 | } 20 | \examples{ 21 | 22 | constraints.checkMinLength(constraint = list(3), value = "hi") 23 | 24 | constraints.checkMinLength(constraint = 2, value = "hello") 25 | } 26 | \seealso{ 27 | \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications} 28 | } 29 | -------------------------------------------------------------------------------- /man/constraints.checkMinimum.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/constraints.checkMinimum.R 3 | \name{constraints.checkMinimum} 4 | \alias{constraints.checkMinimum} 5 | \title{Check if minimum constraint is met} 6 | \usage{ 7 | constraints.checkMinimum(constraint, value) 8 | } 9 | \arguments{ 10 | \item{constraint}{numeric constraint value} 11 | 12 | \item{value}{numeric value to meet the constraint} 13 | } 14 | \value{ 15 | TRUE if value is equal to or greater than the constraint 16 | } 17 | \description{ 18 | Specifies a minimum value for a field. This is different to \code{minLength} which checks the number of items in the value. 19 | A minimum value constraint checks whether a field value is greater than or equal to the specified value. 20 | The range checking depends on the type of the field. E.g. an integer field may have a minimum value of 100. 21 | If a minimum value constraint is specified then the field descriptor \code{MUST} contain a type key. 22 | } 23 | \examples{ 24 | 25 | constraints.checkMinimum(constraint = list(2), value = 1) 26 | 27 | constraints.checkMinimum(constraint = 2, value = 3) 28 | } 29 | \seealso{ 30 | \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications} 31 | } 32 | -------------------------------------------------------------------------------- /man/constraints.checkPattern.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/constraints.checkPattern.R 3 | \name{constraints.checkPattern} 4 | \alias{constraints.checkPattern} 5 | \title{Pattern matching} 6 | \usage{ 7 | constraints.checkPattern(constraint, value) 8 | } 9 | \arguments{ 10 | \item{constraint}{character vector where matches are sought} 11 | 12 | \item{value}{character string to be matched} 13 | } 14 | \value{ 15 | TRUE if the pattern constraint is met 16 | } 17 | \description{ 18 | Search for pattern matches (value) within a character vector (constraint). 19 | A regular expression is used to test field values. 20 | If the regular expression matches then the value is valid. 21 | The values of this field \code{MUST} conform to the standard 22 | \href{http://www.w3.org/TR/xmlschema-2/#regexs}{XML Schema regular expression syntax}. 23 | } 24 | \examples{ 25 | 26 | constraints.checkPattern(constraint = '^test$', value = 'test') 27 | 28 | constraints.checkPattern(constraint = '^test$', value = 'TEST') 29 | } 30 | \seealso{ 31 | \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications} 32 | } 33 | -------------------------------------------------------------------------------- /man/constraints.checkRequired.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/constraints.checkRequired.R 3 | \name{constraints.checkRequired} 4 | \alias{constraints.checkRequired} 5 | \title{Check if a field is required} 6 | \usage{ 7 | constraints.checkRequired(constraint, value) 8 | } 9 | \arguments{ 10 | \item{constraint}{set TRUE to check required values} 11 | 12 | \item{value}{value to check} 13 | } 14 | \value{ 15 | TRUE if field is required 16 | } 17 | \description{ 18 | Indicates whether this field is allowed to be \code{NULL}. 19 | If required is \code{TRUE}, then \code{NULL} is disallowed. 20 | See the section on \href{https://specs.frictionlessdata.io//table-schema/#missing-values}{missingValues} for how, 21 | in the physical representation of the data, strings can represent \code{NULL} values. 22 | } 23 | \examples{ 24 | 25 | constraints.checkRequired(constraint = FALSE, value = 1) 26 | 27 | constraints.checkRequired(constraint = TRUE, value = 0) 28 | 29 | constraints.checkRequired(constraint = TRUE, value = NULL) 30 | 31 | constraints.checkRequired(constraint = TRUE, value = "undefined") 32 | 33 | } 34 | \seealso{ 35 | \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications} 36 | } 37 | -------------------------------------------------------------------------------- /man/constraints.checkUnique.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/constraints.checkUnique.R 3 | \name{constraints.checkUnique} 4 | \alias{constraints.checkUnique} 5 | \title{Check if a field is unique} 6 | \usage{ 7 | constraints.checkUnique(constraint, value) 8 | } 9 | \arguments{ 10 | \item{constraint}{set TRUE to check unique values} 11 | 12 | \item{value}{value to check} 13 | } 14 | \value{ 15 | TRUE if field is unique 16 | } 17 | \description{ 18 | If \code{TRUE}, then all values for that field \code{MUST} be unique within the data file in which it is found. 19 | } 20 | \examples{ 21 | 22 | constraints.checkUnique(constraint = FALSE, value = "any") 23 | 24 | constraints.checkUnique(constraint = TRUE, value = "any") 25 | 26 | } 27 | \seealso{ 28 | \href{https://specs.frictionlessdata.io//table-schema/#constraints}{Constraints specifications} 29 | } 30 | -------------------------------------------------------------------------------- /man/durations.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castDuration.R 3 | \name{durations} 4 | \alias{durations} 5 | \title{Durations} 6 | \usage{ 7 | durations(years = 0, months = 0, days = 0, hours = 0, minutes = 0, seconds = 0) 8 | } 9 | \arguments{ 10 | \item{years}{years} 11 | 12 | \item{months}{months} 13 | 14 | \item{days}{days} 15 | 16 | \item{hours}{hours} 17 | 18 | \item{minutes}{minutes} 19 | 20 | \item{seconds}{seconds} 21 | } 22 | \description{ 23 | Help function to use with \code{\link{types.castDuration}} 24 | } 25 | \seealso{ 26 | \code{\link{types.castDuration}} 27 | } 28 | -------------------------------------------------------------------------------- /man/helpers.expandFieldDescriptor.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{helpers.expandFieldDescriptor} 4 | \alias{helpers.expandFieldDescriptor} 5 | \title{Expand Field Descriptor} 6 | \usage{ 7 | helpers.expandFieldDescriptor(descriptor) 8 | } 9 | \arguments{ 10 | \item{descriptor}{descriptor} 11 | } 12 | \description{ 13 | Helper function to expand field descriptor 14 | } 15 | -------------------------------------------------------------------------------- /man/helpers.expandSchemaDescriptor.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{helpers.expandSchemaDescriptor} 4 | \alias{helpers.expandSchemaDescriptor} 5 | \title{Expand Schema Descriptor} 6 | \usage{ 7 | helpers.expandSchemaDescriptor(descriptor) 8 | } 9 | \arguments{ 10 | \item{descriptor}{descriptor} 11 | } 12 | \description{ 13 | Helper function to expand schema descriptor 14 | } 15 | -------------------------------------------------------------------------------- /man/helpers.from.json.to.list.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{helpers.from.json.to.list} 4 | \alias{helpers.from.json.to.list} 5 | \title{Convert json to list} 6 | \usage{ 7 | helpers.from.json.to.list(lst) 8 | } 9 | \arguments{ 10 | \item{lst}{list} 11 | } 12 | \description{ 13 | Convert json to list 14 | } 15 | -------------------------------------------------------------------------------- /man/helpers.from.list.to.json.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{helpers.from.list.to.json} 4 | \alias{helpers.from.list.to.json} 5 | \title{Convert list to json} 6 | \usage{ 7 | helpers.from.list.to.json(json) 8 | } 9 | \arguments{ 10 | \item{json}{json string} 11 | } 12 | \description{ 13 | Convert list to json 14 | } 15 | -------------------------------------------------------------------------------- /man/helpers.retrieveDescriptor.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{helpers.retrieveDescriptor} 4 | \alias{helpers.retrieveDescriptor} 5 | \title{Retrieve Descriptor} 6 | \usage{ 7 | helpers.retrieveDescriptor(descriptor) 8 | } 9 | \arguments{ 10 | \item{descriptor}{descriptor} 11 | } 12 | \description{ 13 | Helper function to retrieve descriptor 14 | } 15 | -------------------------------------------------------------------------------- /man/infer.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/infer.R 3 | \name{infer} 4 | \alias{infer} 5 | \title{Infer source schema} 6 | \usage{ 7 | infer(source, options = list()) 8 | } 9 | \arguments{ 10 | \item{source}{data source, one of: 11 | \itemize{ 12 | \item string with the local CSV file (path) 13 | \item string with the remote CSV file (url) 14 | \item list of lists representing the rows 15 | \item readable stream with CSV file contents 16 | \item function returning readable stream with CSV file contents 17 | }} 18 | 19 | \item{options}{any \code{Table.load} options} 20 | } 21 | \value{ 22 | Schema descriptor 23 | } 24 | \description{ 25 | Given data source and headers infer will return a Table Schema based on the data values. 26 | } 27 | \examples{ 28 | # list of lists data source 29 | source = list( 30 | list("id"= 1, 31 | "age"= 39, 32 | "name"= "Paul"), 33 | list("id"= 2, 34 | "age"= 23, 35 | "name"= "Jimmy"), 36 | list("id"= 3, 37 | "age"= 36, 38 | "name"= "Jane"), 39 | list("id"= 4, 40 | "age"= 28, 41 | "name"= "Judy")) 42 | 43 | infer(source, options=list(headers=list("id","age","name")))$fields 44 | 45 | } 46 | -------------------------------------------------------------------------------- /man/is.binary.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{is.binary} 4 | \alias{is.binary} 5 | \title{Is binary} 6 | \usage{ 7 | is.binary(x) 8 | } 9 | \arguments{ 10 | \item{x}{input value to check} 11 | } 12 | \value{ 13 | TRUE if binary 14 | } 15 | \description{ 16 | Is binary 17 | } 18 | -------------------------------------------------------------------------------- /man/is.email.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{is.email} 4 | \alias{is.email} 5 | \title{Is email} 6 | \usage{ 7 | is.email(x) 8 | } 9 | \arguments{ 10 | \item{x}{email string} 11 | } 12 | \value{ 13 | TRUE if x is email 14 | } 15 | \description{ 16 | Is email 17 | } 18 | -------------------------------------------------------------------------------- /man/is.uri.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{is.uri} 4 | \alias{is.uri} 5 | \title{Is uri} 6 | \usage{ 7 | is.uri(uri) 8 | } 9 | \arguments{ 10 | \item{uri}{uri input} 11 | } 12 | \value{ 13 | TRUE if uri string 14 | } 15 | \description{ 16 | Is uri 17 | } 18 | -------------------------------------------------------------------------------- /man/is.uuid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{is.uuid} 4 | \alias{is.uuid} 5 | \title{Is uuid} 6 | \usage{ 7 | is.uuid(x) 8 | } 9 | \arguments{ 10 | \item{x}{character} 11 | } 12 | \value{ 13 | TRUE if uuid 14 | } 15 | \description{ 16 | Is uuid 17 | } 18 | -------------------------------------------------------------------------------- /man/is.valid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/is.valid.R 3 | \name{is.valid} 4 | \alias{is.valid} 5 | \title{Is valid} 6 | \usage{ 7 | is.valid(descriptor, schema = NULL) 8 | } 9 | \arguments{ 10 | \item{descriptor}{descriptor, one of: 11 | \itemize{ 12 | \item string with the local CSV file (path) 13 | \item string with the remote CSV file (url) 14 | \item list object 15 | }} 16 | 17 | \item{schema}{Contents of the json schema, or a filename containing a schema} 18 | } 19 | \value{ 20 | \code{TRUE} if valid 21 | } 22 | \description{ 23 | Validate a descriptor over a schema 24 | } 25 | -------------------------------------------------------------------------------- /man/is_empty.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{is_empty} 4 | \alias{is_empty} 5 | \title{Is empty} 6 | \usage{ 7 | is_empty(x) 8 | } 9 | \arguments{ 10 | \item{x}{list object} 11 | } 12 | \description{ 13 | Is empty list 14 | } 15 | -------------------------------------------------------------------------------- /man/is_integer.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{is_integer} 4 | \alias{is_integer} 5 | \title{Is integer} 6 | \usage{ 7 | is_integer(x) 8 | } 9 | \arguments{ 10 | \item{x}{number} 11 | } 12 | \description{ 13 | Is integer 14 | } 15 | -------------------------------------------------------------------------------- /man/is_object.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{is_object} 4 | \alias{is_object} 5 | \title{Is object} 6 | \usage{ 7 | is_object(x) 8 | } 9 | \arguments{ 10 | \item{x}{list, array, json string} 11 | } 12 | \description{ 13 | Is object 14 | } 15 | -------------------------------------------------------------------------------- /man/schema.load.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/schema.R 3 | \name{Schema.load} 4 | \alias{Schema.load} 5 | \title{Instantiate \code{Schema} class} 6 | \usage{ 7 | Schema.load(descriptor, strict=FALSE, caseInsensitiveHeaders = FALSE) 8 | } 9 | \arguments{ 10 | \item{descriptor}{schema descriptor, a JSON string, URL or file} 11 | 12 | \item{strict}{flag to alter validation behaviour: 13 | \itemize{ 14 | \item{if \code{FALSE} error will not be raised and all error will be collected in \code{schema$errors}} 15 | \item{if \code{TRUE} any validation error will be raised immediately} 16 | }} 17 | 18 | \item{caseInsensitiveHeaders}{default is set to \code{FALSE}} 19 | } 20 | \value{ 21 | \code{\link{Schema}} class object 22 | } 23 | \description{ 24 | Factory method to instantiate \code{Schema} class. 25 | This method is async and it should be used with \code{\link[future]{value}} keyword from 26 | \href{https://CRAN.R-project.org/package=future}{future} package. 27 | } 28 | \examples{ 29 | SCHEMA <- '{"fields": [ 30 | {"name": "id", "type": "string", "constraints": {"required": true}}, 31 | {"name": "height", "type": "number"}, 32 | {"name": "age", "type": "integer"}, 33 | {"name": "name", "type": "string", "constraints": {"required": true}}, 34 | {"name": "occupation", "type": "string"} 35 | ]}' 36 | 37 | # instantiate Schema class 38 | def = Schema.load(descriptor = SCHEMA) 39 | schema = future::value(def) 40 | 41 | # correct number of fields 42 | length(schema$fields) 43 | 44 | # correct field names 45 | schema$fieldNames 46 | 47 | # convert row 48 | row = list('string', '10.0', '1', 'string', 'string') 49 | castRow = schema$castRow(row) 50 | castRow 51 | 52 | SCHEMA_MIN <- '{ 53 | "fields": [ 54 | {"name": "id"}, 55 | {"name": "height"} 56 | ]}' 57 | 58 | # load schema 59 | def2 = Schema.load(descriptor = SCHEMA_MIN) 60 | schema2 = future::value(def2) 61 | 62 | # set default types if not provided 63 | schema2$fields[[1]]$type 64 | schema2$fields[[2]]$type 65 | 66 | # fields are not required by default 67 | schema2$fields[[1]]$required 68 | schema2$fields[[2]]$required 69 | 70 | 71 | #work in strict mode 72 | descriptor = '{"fields": [{"name": "name", "type": "string"}]}' 73 | def3 = Schema.load(descriptor = descriptor, strict = TRUE) 74 | schema3 = future::value(def3) 75 | schema3$valid 76 | 77 | # work in non-strict mode 78 | descriptor = '{"fields": [{"name": "name", "type": "string"}]}' 79 | def4 = Schema.load(descriptor = descriptor, strict = FALSE) 80 | schema4 = future::value(def4) 81 | schema4$valid 82 | 83 | # work with primary/foreign keys as arrays 84 | descriptor2 = '{ 85 | "fields": [{"name": "name"}], 86 | "primaryKey": ["name"], 87 | "foreignKeys": [{ 88 | "fields": ["parent_id"], 89 | "reference": {"resource": "resource", "fields": ["id"]} 90 | }]}' 91 | 92 | def5 = Schema.load(descriptor2) 93 | schema5 = future::value(def5) 94 | 95 | schema5$primaryKey 96 | schema5$foreignKeys 97 | 98 | 99 | # work with primary/foreign keys as string 100 | descriptor3 = '{ 101 | "fields": [{"name": "name"}], 102 | "primaryKey": "name", 103 | "foreignKeys": [{ 104 | "fields": "parent_id", 105 | "reference": {"resource": "resource", "fields": "id"} 106 | }]}' 107 | 108 | def6 = Schema.load(descriptor3) 109 | schema6 = future::value(def6) 110 | schema6$primaryKey 111 | schema6$foreignKeys 112 | 113 | } 114 | \seealso{ 115 | \code{\link{Schema}}, \href{https://specs.frictionlessdata.io//table-schema/}{Table Schema Specifications} 116 | } 117 | -------------------------------------------------------------------------------- /man/types.castAny.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castAny.R 3 | \name{types.castAny} 4 | \alias{types.castAny} 5 | \title{Cast any value} 6 | \usage{ 7 | types.castAny(format, value) 8 | } 9 | \arguments{ 10 | \item{format}{any format is accepted} 11 | 12 | \item{value}{any value to cast} 13 | } 14 | \description{ 15 | Cast any value 16 | } 17 | \details{ 18 | Any type or format is accepted. 19 | } 20 | \examples{ 21 | 22 | types.castAny(format = "default", value = 1) 23 | 24 | types.castAny(format = "default", value = "1") 25 | 26 | types.castAny(format = "default", value = "") 27 | 28 | types.castAny(format = "default", value = TRUE) 29 | 30 | } 31 | \seealso{ 32 | \href{https://specs.frictionlessdata.io//table-schema/#any}{Types and formats specifications} 33 | } 34 | -------------------------------------------------------------------------------- /man/types.castArray.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castArray.R 3 | \name{types.castArray} 4 | \alias{types.castArray} 5 | \title{Cast array} 6 | \usage{ 7 | types.castArray(format, value) 8 | } 9 | \arguments{ 10 | \item{format}{no options (other than the default)} 11 | 12 | \item{value}{lists, or valid JSON format arrays to cast} 13 | } 14 | \description{ 15 | Cast array is used for list objects 16 | } 17 | \seealso{ 18 | \code{\link{types.castList}}, 19 | \href{https://specs.frictionlessdata.io//table-schema/#array}{Types and formats specifications} 20 | } 21 | -------------------------------------------------------------------------------- /man/types.castBoolean.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castBoolean.R 3 | \name{types.castBoolean} 4 | \alias{types.castBoolean} 5 | \title{Cast boolean} 6 | \usage{ 7 | types.castBoolean( 8 | format = "default", 9 | value, 10 | options = { 11 | } 12 | ) 13 | } 14 | \arguments{ 15 | \item{format}{no options (other than the default)} 16 | 17 | \item{value}{boolean to cast} 18 | 19 | \item{options}{specify additioanl true values or/and falsevalues} 20 | } 21 | \description{ 22 | Cast boolean values 23 | } 24 | \details{ 25 | In the physical representations of data where boolean values are represented with strings, 26 | the values set in \code{trueValues} and \code{falseValues} are to be cast to their logical representation as booleans. 27 | \code{trueValues} and \code{falseValues} are lists which can be customised to user need. 28 | The default values for these are in the additional properties section below. 29 | 30 | The boolean field can be customised with these additional properties: 31 | \itemize{ 32 | \item{trueValues: ["true", "True", "TRUE", "1"]} 33 | \item{falseValues: ["false", "False", "FALSE", "0"]} 34 | } 35 | } 36 | \examples{ 37 | 38 | types.castBoolean(format = "default", value = TRUE) 39 | 40 | types.castBoolean(format = "default", value = "true") 41 | 42 | types.castBoolean(format = "default", value = "1") 43 | 44 | types.castBoolean(format = "default", value = "0") 45 | 46 | # set options with additional true value 47 | types.castBoolean(format = "default", value = "yes", list(trueValues = list("yes"))) 48 | 49 | # set options with additional false value 50 | types.castBoolean(format = "default", value = "no", list(falseValues = list("no"))) 51 | 52 | } 53 | \seealso{ 54 | \href{https://specs.frictionlessdata.io//table-schema/#boolean}{Types and formats specifications} 55 | } 56 | -------------------------------------------------------------------------------- /man/types.castDate.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castDate.R 3 | \name{types.castDate} 4 | \alias{types.castDate} 5 | \title{Cast date} 6 | \usage{ 7 | types.castDate(format = "default", value) 8 | } 9 | \arguments{ 10 | \item{format}{Available options are \code{"default"}, \code{"any"}, and \code{""}, where: 11 | \describe{ 12 | \item{\code{default}}{An ISO8601 format string: 13 | \describe{ 14 | \item{\code{date:}}{This \code{MUST} be in ISO8601 format \code{YYYY-MM-DD}.} 15 | \item{\code{datetime:}}{A date-time. This \code{MUST} be in ISO 8601 format \code{YYYY-MM-DDThh:mm:ssZ} in UTC time.} 16 | \item{\code{time:}}{A time without a date.} 17 | } 18 | } 19 | \item{\code{any}}{Any parsable representation of the type. The implementing library 20 | may attempt to parse the datetime using various strategies, e.g., 21 | \href{https://CRAN.R-project.org/package=lubridate}{lubridate}, 22 | \href{https://CRAN.R-project.org/package=parsedate}{parsedate}, 23 | \code{\link[base]{strptime}}, or \code{\link[base]{DateTimeClasses}}.} 24 | \item{\code{}}{Date/time values in this field can be parsed according to the specified \code{pattern}. 25 | \code{} MUST follow the syntax of \code{\link[base]{strptime}}. That is, values in this field should be parseable by R using the given pattern.} 26 | }} 27 | 28 | \item{value}{Date to cast.} 29 | } 30 | \description{ 31 | Cast date without a time. 32 | } 33 | \examples{ 34 | types.castDate(format = "default", value = as.Date("2019-1-1")) 35 | 36 | types.castDate(format = "default", value = "2019-1-1") 37 | 38 | types.castDate(format = "any", value = "2019-1-1") 39 | 40 | types.castDate(format = "\%d/\%m/\%y", value = "21/11/06") 41 | 42 | types.castDate(format = "\%d/\%m/\%y", value = as.Date("2019-1-1")) 43 | 44 | } 45 | \seealso{ 46 | \href{https://specs.frictionlessdata.io//table-schema/#date}{Types and formats specifications}, 47 | \code{\link[base]{strptime}}, 48 | \code{\link[base]{DateTimeClasses}}, 49 | \code{\link[parsedate]{parsedate-package}}, 50 | \code{\link[lubridate]{lubridate-package}}. 51 | } 52 | -------------------------------------------------------------------------------- /man/types.castDatetime.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castDatetime.R 3 | \name{types.castDatetime} 4 | \alias{types.castDatetime} 5 | \title{Cast datetime} 6 | \usage{ 7 | types.castDatetime(format = "\%Y-\%m-\%dT\%H:\%M:\%SZ", value) 8 | } 9 | \arguments{ 10 | \item{format}{available options are "default", "any", and "" where 11 | \describe{ 12 | \item{\code{default }}{An ISO8601 format string e.g. YYYY-MM-DDThh:mm:ssZ in UTC time} 13 | \item{\code{any }}{As for \code{\link{types.castDate}}} 14 | \item{\code{ }}{As for \code{\link{types.castDate}}} 15 | }} 16 | 17 | \item{value}{datetime to cast} 18 | } 19 | \description{ 20 | Cast date with time 21 | } 22 | \examples{ 23 | 24 | types.castDatetime(format = "default", value = "2014-01-01T06:00:00Z") 25 | 26 | types.castDatetime(format = "\%d/\%m/\%y \%H:\%M", value = "21/11/06 16:30") 27 | 28 | } 29 | \seealso{ 30 | \href{https://specs.frictionlessdata.io//table-schema/#datetime}{Types and formats specifications}, 31 | \code{\link[base]{strptime}}, \code{\link[base]{DateTimeClasses}}, 32 | \code{\link[parsedate]{parsedate-package}} and 33 | \code{\link[lubridate]{lubridate-package}}. 34 | } 35 | -------------------------------------------------------------------------------- /man/types.castDuration.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castDuration.R 3 | \name{types.castDuration} 4 | \alias{types.castDuration} 5 | \title{Cast duration of time} 6 | \usage{ 7 | types.castDuration(format = "default", value) 8 | } 9 | \arguments{ 10 | \item{format}{no options (other than the default)} 11 | 12 | \item{value}{duration to cast} 13 | } 14 | \description{ 15 | Cast duration of time 16 | } 17 | \details{ 18 | We follow the definition of \href{https://www.w3.org/TR/xmlschema-2/#duration}{XML Schema duration datatype} 19 | directly and that definition is implicitly inlined here. 20 | 21 | To summarize: the lexical representation for duration is the \href{https://en.wikipedia.org/wiki/ISO_8601#Durations}{ISO 8601} 22 | extended format PnYnMnDTnHnMnS, where nY represents the number of years, nM the number of months, nD the number of days, 23 | 'T' is the date/time separator, nH the number of hours, nM the number of minutes and nS the number of seconds. 24 | The number of seconds can include decimal digits to arbitrary precision. 25 | Date and time elements including their designator may be omitted if their value is zero, 26 | and lower order elements may also be omitted for reduced precision. 27 | } 28 | \examples{ 29 | 30 | types.castDuration(format = "default", value = durations(years= 10)) 31 | 32 | types.castDuration(format = "default", value = "P1Y10M3DT5H11M7S") 33 | 34 | } 35 | \seealso{ 36 | \href{https://specs.frictionlessdata.io//table-schema/#duration}{Types and formats specifications}, 37 | \code{\link[lubridate]{lubridate-package}}. 38 | } 39 | -------------------------------------------------------------------------------- /man/types.castGeojson.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castGeojson.R 3 | \name{types.castGeojson} 4 | \alias{types.castGeojson} 5 | \title{Cast JSON object according to GeoJSON or TopoJSON spec} 6 | \usage{ 7 | types.castGeojson(format, value) 8 | } 9 | \arguments{ 10 | \item{format}{default is a geojson object as per the \href{https://geojson.org/}{GeoJSON spec} or 11 | topojson object as per the \href{https://github.com/topojson/topojson-specification/blob/master/README.md}{TopoJSON spec}} 12 | 13 | \item{value}{GeoJSON to cast} 14 | } 15 | \description{ 16 | Cast JSON object according to GeoJSON or TopoJSON spec 17 | } 18 | \seealso{ 19 | \href{https://specs.frictionlessdata.io//table-schema/#geojson}{Types and formats specifications} 20 | } 21 | -------------------------------------------------------------------------------- /man/types.castGeopoint.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castGeopoint.R 3 | \name{types.castGeopoint} 4 | \alias{types.castGeopoint} 5 | \title{Cast geographic point} 6 | \usage{ 7 | types.castGeopoint(format, value) 8 | } 9 | \arguments{ 10 | \item{format}{available options are "default", "array" and "object", where 11 | \describe{ 12 | \item{\code{default }}{A string of the pattern "lon, lat", where \code{lon} is the longitude 13 | and \code{lat} is the latitude (note the space is optional after the \code{,}). E.g. \code{"90, 45"}.} 14 | \item{\code{array }}{A JSON array, or a string parsable as a JSON array, of exactly two items, 15 | where each item is a number, and the first item is \code{lon} and the second item is \code{lat} e.g. \code{[90, 45]}.} 16 | \item{\code{object }}{A JSON object with exactly two keys, \code{lat} and \code{lon} and each value is a number e.g. \code{{"lon": 90, "lat": 45}}.} 17 | }} 18 | 19 | \item{value}{geopoint to cast} 20 | } 21 | \description{ 22 | Cast geographic point 23 | } 24 | \examples{ 25 | 26 | types.castGeopoint(format = "default", value = list(180, 90)) 27 | 28 | types.castGeopoint(format = "default", value = '180,90') 29 | 30 | types.castGeopoint(format = "default", value = '180, -90') 31 | 32 | types.castGeopoint(format = "array", value = list(180, 90)) 33 | 34 | types.castGeopoint(format = "array", value = '[180, -90]') 35 | 36 | types.castGeopoint(format = "object", value = list(lon = 180, lat = 90)) 37 | 38 | types.castGeopoint(format = "object", value = '{"lon": 180, "lat": 90}') 39 | 40 | } 41 | \seealso{ 42 | \href{https://specs.frictionlessdata.io//table-schema/#geopoint}{Types and formats specifications} 43 | } 44 | -------------------------------------------------------------------------------- /man/types.castInteger.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castInteger.R 3 | \name{types.castInteger} 4 | \alias{types.castInteger} 5 | \title{Cast integer} 6 | \usage{ 7 | types.castInteger( 8 | format, 9 | value, 10 | options = { 11 | } 12 | ) 13 | } 14 | \arguments{ 15 | \item{format}{no options (other than the default)} 16 | 17 | \item{value}{integer to cast} 18 | 19 | \item{options}{named list set bareNumber \code{TRUE} or \code{FALSE}, see details} 20 | } 21 | \description{ 22 | Cast integer. Integer values are indicated in the standard way for any valid integer. 23 | } 24 | \details{ 25 | bareNumber is a boolean field with a default of \code{TRUE}. If \code{TRUE} the physical contents of this field must follow 26 | the formatting constraints already set out. If \code{FALSE} the contents of this field may contain leading 27 | and or trailing non-numeric characters (which implementors MUST therefore strip). 28 | The purpose of \code{bareNumber} is to allow publishers to publish numeric data that contains trailing characters such as percentages 29 | e.g. \code{95}% or leading characters such as currencies e.g. €\code{95} or EUR \code{95}. Note that it is entirely up to implementors what, 30 | if anything, they do with stripped text. 31 | } 32 | \examples{ 33 | types.castInteger(format = "default", value = 1) 34 | 35 | types.castInteger(format = "default", value = "1") 36 | # cast trailing non numeric character 37 | types.castInteger(format = "default", value = "1$", options = list(bareNumber = FALSE)) 38 | 39 | } 40 | \seealso{ 41 | \href{https://specs.frictionlessdata.io//table-schema/#integer}{Types and formats specifications} 42 | } 43 | -------------------------------------------------------------------------------- /man/types.castList.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castList.R 3 | \name{types.castList} 4 | \alias{types.castList} 5 | \title{Cast list} 6 | \usage{ 7 | types.castList(format, value) 8 | } 9 | \arguments{ 10 | \item{format}{no options (other than the default)} 11 | 12 | \item{value}{lists, or valid JSON format arrays to cast} 13 | } 14 | \description{ 15 | cast list 16 | } 17 | \examples{ 18 | 19 | types.castList(format = "default", value = list()) 20 | 21 | types.castList(format = "default", value = list('key', 'value')) 22 | 23 | types.castList(format = "default", value = '["key", "value"]') # cast valid json array 24 | 25 | } 26 | \seealso{ 27 | \href{https://specs.frictionlessdata.io//table-schema/#array}{Types and formats specifications} 28 | } 29 | -------------------------------------------------------------------------------- /man/types.castNumber.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castNumber.R 3 | \name{types.castNumber} 4 | \alias{types.castNumber} 5 | \title{Cast numbers of any kind including decimals} 6 | \usage{ 7 | types.castNumber( 8 | format, 9 | value, 10 | options = { 11 | } 12 | ) 13 | } 14 | \arguments{ 15 | \item{format}{no options (other than the default)} 16 | 17 | \item{value}{number to cast} 18 | 19 | \item{options}{available options are "decimalChar", "groupChar" and "bareNumber", where 20 | \describe{ 21 | \item{\code{decimalChar }}{A string whose value is used to represent a decimal point within the number. The default value is ".".} 22 | \item{\code{groupChar }}{A string whose value is used to group digits within the number. The default value is null. A common value is "," e.g. "100,000".} 23 | \item{\code{bareNumber }}{A boolean field with a default of \code{TRUE} If \code{TRUE} the physical contents of this field must follow 24 | the formatting constraints already set out. If \code{FALSE} the contents of this field may contain leading and/or 25 | trailing non-numeric characters (which implementors MUST therefore strip). The purpose of \code{bareNumber} is to allow publishers 26 | to publish numeric data that contains trailing characters such as percentages e.g. 95% or leading characters such as currencies 27 | e.g. €95 or EUR 95. Note that it is entirely up to implementors what, if anything, they do with stripped text.} 28 | }} 29 | } 30 | \description{ 31 | Cast numbers of any kind including decimals. 32 | } 33 | \details{ 34 | The lexical formatting follows that of decimal in \href{https://www.w3.org/TR/xmlschema-2/#decimal}{XMLSchema}: a non-empty finite-length sequence 35 | of decimal digits separated by a period as a decimal indicator. An optional leading sign is allowed. If the sign is omitted, "+" is assumed. 36 | Leading and trailing zeroes are optional. If the fractional part is zero, the period and following zero(es) can be omitted. 37 | For example: '-1.23', '12678967.543233', '+100000.00', '210'. 38 | 39 | The following special string values are permitted (case need not be respected): 40 | \itemize{ 41 | \item{\code{NaN}: not a number} 42 | \item{\code{INF}: positive infinity} 43 | \item{\code{-INF}: negative infinity} 44 | } 45 | 46 | A number MAY also have a trailing: 47 | \itemize{ 48 | \item{\code{exponent}: this \code{MUST} consist of an E followed by an optional + or - sign followed by one or more decimal digits (0-9)} 49 | } 50 | } 51 | \examples{ 52 | 53 | types.castNumber(format = "default", value = 1) 54 | types.castNumber(format = "default", value = "1.0") 55 | 56 | # cast number with percent sign 57 | types.castNumber(format = "default", value = "10.5\%", options = list(bareNumber = FALSE)) 58 | 59 | # cast number with comma group character 60 | types.castNumber(format = "default", value = "1,000", options = list(groupChar = ',')) 61 | types.castNumber(format = "default", value = "10,000.50", options = list(groupChar = ',')) 62 | 63 | # cast number with "#" group character and "&" as decimal character 64 | types.castNumber(format = "default", value = "10#000&50", 65 | options = list(groupChar = '#', decimalChar = '&')) 66 | 67 | } 68 | \seealso{ 69 | \href{https://specs.frictionlessdata.io//table-schema/#number}{Types and formats specifications} 70 | } 71 | -------------------------------------------------------------------------------- /man/types.castObject.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castObject.R 3 | \name{types.castObject} 4 | \alias{types.castObject} 5 | \title{Cast object} 6 | \usage{ 7 | types.castObject(format, value) 8 | } 9 | \arguments{ 10 | \item{format}{no options (other than the default)} 11 | 12 | \item{value}{object to cast} 13 | } 14 | \description{ 15 | Cast object data which is lists or valid JSON. 16 | } 17 | \examples{ 18 | 19 | types.castObject(format = "default", value = list()) 20 | 21 | types.castObject(format = "default", value = "{}") 22 | 23 | types.castObject(format = "default", value = '{"key": "value"}') 24 | 25 | } 26 | \seealso{ 27 | \href{https://specs.frictionlessdata.io//table-schema/#object}{Types and formats specifications} 28 | } 29 | -------------------------------------------------------------------------------- /man/types.castString.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castString.R 3 | \name{types.castString} 4 | \alias{types.castString} 5 | \title{Cast string} 6 | \usage{ 7 | types.castString(format, value) 8 | } 9 | \arguments{ 10 | \item{format}{available options are "default", "email", "uri", "binary" and "uuid", where 11 | \describe{ 12 | \item{\code{default }}{Any valid string.} 13 | \item{\code{email }}{A valid email address.} 14 | \item{\code{uri }}{A valid URI.} 15 | \item{\code{binary }}{A base64 encoded string representing binary data.} 16 | \item{\code{uuid }}{A string that is a uuid.} 17 | }} 18 | 19 | \item{value}{string to cast} 20 | } 21 | \description{ 22 | Cast string that is, sequences of characters. 23 | } 24 | \examples{ 25 | 26 | # cast any string 27 | types.castString(format = "default", value = "string") 28 | 29 | # cast email 30 | types.castString(format = "email", value = "name@gmail.com") 31 | \dontshow{ 32 | # cast uri 33 | types.castString(format = "uri", value = "http://google.com") 34 | } 35 | # cast binary 36 | types.castString(format = "binary", value = "dGVzdA==") 37 | 38 | # cast uuid 39 | types.castString(format = "uuid", value = "95ecc380-afe9-11e4-9b6c-751b66dd541e") 40 | 41 | } 42 | \seealso{ 43 | \href{https://specs.frictionlessdata.io//table-schema/#string}{Types and formats specifications} 44 | } 45 | -------------------------------------------------------------------------------- /man/types.castTime.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castTime.R 3 | \name{types.castTime} 4 | \alias{types.castTime} 5 | \title{Cast time without a date} 6 | \usage{ 7 | types.castTime(format = "\%H:\%M:\%S", value) 8 | } 9 | \arguments{ 10 | \item{format}{available options are "default", "any", and "" where 11 | \describe{ 12 | \item{\code{default }}{An ISO8601 time string e.g. hh:mm:ss} 13 | \item{\code{any }}{As for \code{\link{types.castDate}}} 14 | \item{\code{ }}{As for \code{\link{types.castDate}}} 15 | }} 16 | 17 | \item{value}{time to cast} 18 | } 19 | \description{ 20 | Cast time without a date 21 | } 22 | \examples{ 23 | 24 | types.castTime(format = "default", value = '06:00:00') 25 | 26 | } 27 | \seealso{ 28 | \href{https://specs.frictionlessdata.io//table-schema/#time}{Types and formats specifications}, 29 | \code{\link[base]{strptime}}, \code{\link[base]{DateTimeClasses}}, 30 | \code{\link[parsedate]{parsedate-package}} and 31 | \code{\link[lubridate]{lubridate-package}}. 32 | } 33 | -------------------------------------------------------------------------------- /man/types.castYear.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castYear.R 3 | \name{types.castYear} 4 | \alias{types.castYear} 5 | \title{Cast year} 6 | \usage{ 7 | types.castYear(format, value) 8 | } 9 | \arguments{ 10 | \item{format}{no options (other than the default)} 11 | 12 | \item{value}{year to cast} 13 | } 14 | \description{ 15 | Cast year. A calendar year as per \href{https://www.w3.org/TR/xmlschema-2/#gYear}{XMLSchema gYear}. 16 | Usual lexical representation is: YYYY. 17 | } 18 | \examples{ 19 | 20 | types.castYear(format = "default", value = 2000) 21 | 22 | types.castYear(format = "default", value = "2010") 23 | 24 | } 25 | \seealso{ 26 | \href{https://specs.frictionlessdata.io//table-schema/#year}{Types and formats specifications} 27 | } 28 | -------------------------------------------------------------------------------- /man/types.castYearmonth.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/types.castYearmonth.R 3 | \name{types.castYearmonth} 4 | \alias{types.castYearmonth} 5 | \title{Cast a specific month in a specific year} 6 | \usage{ 7 | types.castYearmonth(format, value) 8 | } 9 | \arguments{ 10 | \item{format}{no options (other than the default)} 11 | 12 | \item{value}{list or string with yearmonth to cast} 13 | } 14 | \description{ 15 | Cast a specific month in a specific year as per \href{https://www.w3.org/TR/xmlschema-2/#gYearMonth}{XMLSchema gYearMonth}. 16 | Usual lexical representation is: YYYY-MM. 17 | } 18 | \examples{ 19 | 20 | types.castYearmonth(format = "default", value = list(2000, 10)) 21 | 22 | types.castYearmonth(format = "default", value = "2018-11") 23 | 24 | } 25 | \seealso{ 26 | \href{https://specs.frictionlessdata.io//table-schema/#yearmonth}{Types and formats specifications} 27 | } 28 | -------------------------------------------------------------------------------- /man/validate.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/validate.R 3 | \name{validate} 4 | \alias{validate} 5 | \title{validate descriptor} 6 | \usage{ 7 | validate(descriptor) 8 | } 9 | \arguments{ 10 | \item{descriptor}{schema descriptor, one of: 11 | \itemize{ 12 | \item string with the local CSV file (path) 13 | \item string with the remote CSV file (url) 14 | \item list object 15 | }} 16 | } 17 | \value{ 18 | \code{TRUE} on valid 19 | } 20 | \description{ 21 | Validates whether a schema is a validate Table Schema accordingly to the specifications. 22 | It does not validate data against a schema. 23 | } 24 | -------------------------------------------------------------------------------- /man/write_json.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{write_json} 4 | \alias{write_json} 5 | \title{Save json file} 6 | \usage{ 7 | write_json(x, file) 8 | } 9 | \arguments{ 10 | \item{x}{list object} 11 | 12 | \item{file}{file} 13 | } 14 | \description{ 15 | save json 16 | } 17 | -------------------------------------------------------------------------------- /okgr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frictionlessdata/tableschema-r/f5f40bdfca2044753fbbd0f2aeebd1b5e4041181/okgr.png -------------------------------------------------------------------------------- /oklabs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frictionlessdata/tableschema-r/f5f40bdfca2044753fbbd0f2aeebd1b5e4041181/oklabs.png -------------------------------------------------------------------------------- /tableschema-r.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | ProjectId: fb6048d4-5591-4d96-b83f-b050ab808198 3 | 4 | RestoreWorkspace: Default 5 | SaveWorkspace: Default 6 | AlwaysSaveHistory: Default 7 | 8 | EnableCodeIndexing: Yes 9 | UseSpacesForTab: Yes 10 | NumSpacesForTab: 2 11 | Encoding: UTF-8 12 | 13 | RnwWeave: knitr 14 | LaTeX: pdfLaTeX 15 | 16 | BuildType: Package 17 | PackageUseDevtools: Yes 18 | PackageInstallArgs: --no-multiarch --with-keep.source 19 | PackageRoxygenize: rd,collate,namespace,vignette 20 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | Sys.setenv(R_TESTS = "") 2 | library(testthat) 3 | library(tableschema.r) 4 | 5 | test_check("tableschema.r") 6 | -------------------------------------------------------------------------------- /tests/testthat/inst/extdata/data.csv: -------------------------------------------------------------------------------- 1 | city,location 2 | london,"51.50 -0.11" 3 | paris,"48.85 2.30" 4 | rome,N/A 5 | -------------------------------------------------------------------------------- /tests/testthat/inst/extdata/data_delim.csv: -------------------------------------------------------------------------------- 1 | id;name 2 | 1;"abc, ab" 3 | -------------------------------------------------------------------------------- /tests/testthat/inst/extdata/data_delim2.csv: -------------------------------------------------------------------------------- 1 | id,name 2 | 1,"abc, ab" 3 | 2,"cba, ba" 4 | -------------------------------------------------------------------------------- /tests/testthat/inst/extdata/data_infer.csv: -------------------------------------------------------------------------------- 1 | id,age,name 2 | 1,39,Paul 3 | 2,23,Jimmy 4 | 3,36,Jane 5 | 4,28,Judy 6 | -------------------------------------------------------------------------------- /tests/testthat/inst/extdata/data_infer_formats.csv: -------------------------------------------------------------------------------- 1 | id,capital,url 2 | 1,39.00$,http://www.test.com 3 | 2,23.00$,http://www.test.de 4 | 3,36.00$,http://www.test.uk 5 | 4,28.00$,http://www.test.co.il -------------------------------------------------------------------------------- /tests/testthat/inst/extdata/data_infer_row_limit.csv: -------------------------------------------------------------------------------- 1 | id,age,name 2 | 1,39,Paul 3 | 2,23,Jimmy 4 | 3,36,Jane 5 | 4,28,Judy 6 | qwerty,nineteen,Rose 7 | werty,nineteen,Red 8 | erty,nineteen,Rotem 9 | rty,nineteen,Ruth 10 | ty,nineteen,Amber 11 | y,nineteen,Angel 12 | _,nineteen,Angie 13 | -------------------------------------------------------------------------------- /tests/testthat/inst/extdata/data_infer_utf8.csv: -------------------------------------------------------------------------------- 1 | id,age,name 2 | 1,39,Paul 3 | 2,23,Jimmy 4 | 3,36,Jane 5 | 4,28,Judy 6 | 5,37,Iñtërnâtiônàlizætiøn 7 | -------------------------------------------------------------------------------- /tests/testthat/inst/extdata/data_parse_options_default.csv: -------------------------------------------------------------------------------- 1 | id,age,name 2 | 1,39, Paul 3 | 2,23,Jimmy 4 | 3,36,Jane 5 | 4,28,Judy 6 | -------------------------------------------------------------------------------- /tests/testthat/inst/extdata/data_parse_options_delimiter.csv: -------------------------------------------------------------------------------- 1 | id;age;name 2 | 1;39;Paul 3 | 2;23;Jimmy 4 | 3;36;Jane 5 | 4;28;Judy 6 | -------------------------------------------------------------------------------- /tests/testthat/inst/extdata/jsonchar.json: -------------------------------------------------------------------------------- 1 | "{\"fields\":[{\"name\":\"id\",\"type\":\"string\",\"constraints\":{\"required\":true},\"format\":\"default\"},{\"name\":\"height\",\"type\":\"number\",\"format\":\"default\"},{\"name\":\"age\",\"type\":\"integer\",\"format\":\"default\"},{\"name\":\"name\",\"type\":\"string\",\"constraints\":{\"required\":true},\"format\":\"default\"},{\"name\":\"occupation\",\"type\":\"string\",\"format\":\"default\"}],\"missingValues\":[\"\"]}" 2 | 3 | -------------------------------------------------------------------------------- /tests/testthat/inst/extdata/latin1.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frictionlessdata/tableschema-r/f5f40bdfca2044753fbbd0f2aeebd1b5e4041181/tests/testthat/inst/extdata/latin1.csv -------------------------------------------------------------------------------- /tests/testthat/inst/extdata/mathematics.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": [ 3 | { 4 | "description": "Total Number of Grades", 5 | "name": "Grade", 6 | "type": "string" 7 | }, 8 | { 9 | "description": "Grade Awarding Year", 10 | "format": "any", 11 | "name": "Year", 12 | "type": "date" 13 | }, 14 | { 15 | "description": "Education Category (General, Special)", 16 | "name": "Category", 17 | "type": "string" 18 | }, 19 | { 20 | "constraints": { 21 | "level": "Ratio" 22 | }, 23 | "description": "Total number of tested", 24 | "name": "Number_Tested", 25 | "type": "integer" 26 | }, 27 | { 28 | "constraints": { 29 | "level": "Ratio" 30 | }, 31 | "description": "Mean of Scale Core", 32 | "name": "Mean_Scale_Score", 33 | "type": "integer" 34 | }, 35 | { 36 | "constraints": { 37 | "level": "Ratio" 38 | }, 39 | "description": "Score of Level 1", 40 | "name": "Number_Level_1", 41 | "type": "integer" 42 | }, 43 | { 44 | "constraints": { 45 | "level": "Ratio" 46 | }, 47 | "description": "Percentage of Level 1", 48 | "name": "Percentage_Level_1", 49 | "type": "number" 50 | }, 51 | { 52 | "constraints": { 53 | "level": "Ratio" 54 | }, 55 | "description": "Score of Level 2", 56 | "name": "Number_Level_2", 57 | "type": "integer" 58 | }, 59 | { 60 | "constraints": { 61 | "level": "Ratio" 62 | }, 63 | "description": "Percentage of Level 2", 64 | "name": "Percentage_Level_2", 65 | "type": "number" 66 | }, 67 | { 68 | "constraints": { 69 | "level": "Ratio" 70 | }, 71 | "description": "Score of Level 3", 72 | "name": "Number_Level_3", 73 | "type": "integer" 74 | }, 75 | { 76 | "constraints": { 77 | "level": "Ratio" 78 | }, 79 | "description": "Percentage of Level 3", 80 | "name": "Percentage_Level_3", 81 | "type": "number" 82 | }, 83 | { 84 | "constraints": { 85 | "level": "Ratio" 86 | }, 87 | "description": "Score of Level 4", 88 | "name": "Number_Level_4", 89 | "type": "integer" 90 | }, 91 | { 92 | "constraints": { 93 | "level": "Ratio" 94 | }, 95 | "description": "Percentage of Level 4", 96 | "name": "Percentage_Level_4", 97 | "type": "number" 98 | } 99 | ] 100 | } 101 | -------------------------------------------------------------------------------- /tests/testthat/inst/extdata/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": [ 3 | { 4 | "name": "id", 5 | "type": "string", 6 | "constraints": { 7 | "required": true 8 | }, 9 | "format": "default" 10 | }, 11 | { 12 | "name": "height", 13 | "type": "number", 14 | "format": "default" 15 | }, 16 | { 17 | "name": "age", 18 | "type": "integer", 19 | "format": "default" 20 | }, 21 | { 22 | "name": "name", 23 | "type": "string", 24 | "constraints": { 25 | "required": true 26 | }, 27 | "format": "default" 28 | }, 29 | { 30 | "name": "occupation", 31 | "type": "string", 32 | "format": "default" 33 | } 34 | ], 35 | "missingValues": [ 36 | "" 37 | ] 38 | } 39 | 40 | -------------------------------------------------------------------------------- /tests/testthat/inst/extdata/schema2.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": [{ 3 | "name": "id", 4 | "title": "", 5 | "description": "", 6 | "type": "integer", 7 | "format": "default" 8 | }, 9 | { 10 | "name": "capital", 11 | "title": "", 12 | "description": "", 13 | "type": "number" 14 | }, 15 | { 16 | "name": "url", 17 | "title": "", 18 | "description": "", 19 | "type": "string" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /tests/testthat/inst/extdata/schema_valid_full.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": [ 3 | { 4 | "name": "first_name", 5 | "title": "First Name", 6 | "type": "string", 7 | "description": "The first name of the person" 8 | }, 9 | { 10 | "name": "last_name", 11 | "title": "Last Name", 12 | "type": "string", 13 | "description": "The last name of the person" 14 | }, 15 | { 16 | "name": "gender", 17 | "title": "Gender", 18 | "type": "string", 19 | "description": "The gender of the person." 20 | }, 21 | { 22 | "name": "age", 23 | "title": "Age", 24 | "type": "integer", 25 | "description": "The age of this person." 26 | }, 27 | { 28 | "name": "period_employed", 29 | "title": "Period Employed", 30 | "type": "number", 31 | "description": "The period of employment, in years (eg: 2.6 Y)." 32 | }, 33 | { 34 | "name": "employment_start", 35 | "title": "Employment Start", 36 | "type": "date", 37 | "description": "The date this person started employment." 38 | }, 39 | { 40 | "name": "daily_start", 41 | "title": "Daily Start", 42 | "type": "time", 43 | "description": "Usual start time for this person." 44 | }, 45 | { 46 | "name": "daily_end", 47 | "title": "Daily End", 48 | "type": "time", 49 | "description": "Usual end time for this person." 50 | }, 51 | { 52 | "name": "is_management", 53 | "title": "Is Management", 54 | "type": "boolean", 55 | "description": "Is this person part of upper management." 56 | }, 57 | { 58 | "name": "photo", 59 | "title": "Photo", 60 | "type": "string", 61 | "format": "binary", 62 | "description": "A photo of this person." 63 | }, 64 | { 65 | "name": "interests", 66 | "title": "Interests", 67 | "type": "array", 68 | "description": "Declared interests of this person (work-related)." 69 | }, 70 | { 71 | "name": "home_location", 72 | "title": "Home Location", 73 | "type": "geopoint", 74 | "description": "A geopoint for this person's home address." 75 | }, 76 | { 77 | "name": "position_title", 78 | "title": "Position Title", 79 | "type": "string", 80 | "description": "This person's position in the company." 81 | }, 82 | { 83 | "name": "extra", 84 | "title": "Extra", 85 | "type": "object", 86 | "description": "Extra information about this person." 87 | }, 88 | { 89 | "name": "notes", 90 | "title": "Notes", 91 | "type": "any", 92 | "description": "Add any relevant notes for HR." 93 | } 94 | ], 95 | "primaryKey": [ 96 | "first_name", 97 | "last_name", 98 | "period_employed", 99 | "home_location" 100 | ], 101 | "foreignKeys": [ 102 | { 103 | "fields": ["position_title"], 104 | "reference": { 105 | "resource": "positions", 106 | "fields": ["name"] 107 | } 108 | } 109 | ] 110 | } 111 | -------------------------------------------------------------------------------- /tests/testthat/test-constraints.checkEnum.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | 6 | context("constraints.checkEnum") 7 | 8 | # Constants 9 | TESTS <- list( 10 | 11 | list( list(1, 2), 1, TRUE), 12 | 13 | list( list(0, 2), 1, FALSE), 14 | 15 | list( list(), 1, FALSE), 16 | 17 | list( list(), NULL, TRUE) 18 | 19 | ) 20 | 21 | # Tests 22 | 23 | foreach(j = seq_along(TESTS) ) %do% { 24 | 25 | TESTS[[j]] <- setNames(TESTS[[j]], c("constraint", "value", "result")) 26 | 27 | test_that(str_interp('constraint "${TESTS[[j]]$constraint}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 28 | 29 | expect_equal(constraints.checkEnum(TESTS[[j]]$constraint, TESTS[[j]]$value), TESTS[[j]]$result) 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /tests/testthat/test-constraints.checkMaxLength.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | 6 | context("constraints.checkMaxLength") 7 | 8 | # Constants 9 | TESTS <- list( 10 | 11 | list( 0, list(1), FALSE), 12 | 13 | list( 1, list(1), TRUE), 14 | 15 | list( 2, list(1), TRUE), 16 | 17 | list( 2, NULL, TRUE) 18 | 19 | ) 20 | 21 | # Tests 22 | 23 | foreach(j = seq_along(TESTS) ) %do% { 24 | 25 | TESTS[[j]] <- setNames(TESTS[[j]], c("constraint", "value", "result")) 26 | 27 | test_that(str_interp('constraint "${TESTS[[j]]$constraint}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 28 | 29 | expect_equal(constraints.checkMaxLength(TESTS[[j]]$constraint, TESTS[[j]]$value), TESTS[[j]]$result) 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /tests/testthat/test-constraints.checkMaximum.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | 6 | context("constraints.checkMaximum") 7 | 8 | # Constants 9 | TESTS <- list( 10 | 11 | list( 0, 1, FALSE), 12 | 13 | list( 1, 1, TRUE), 14 | 15 | list( 2, 1, TRUE), 16 | 17 | list( 2, NULL, TRUE) 18 | 19 | ) 20 | 21 | # Tests 22 | 23 | foreach(j = seq_along(TESTS) ) %do% { 24 | 25 | TESTS[[j]] <- setNames(TESTS[[j]], c("constraint", "value", "result")) 26 | 27 | test_that(str_interp('constraint "${TESTS[[j]]$constraint}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 28 | 29 | expect_equal(constraints.checkMaximum(TESTS[[j]]$constraint, TESTS[[j]]$value), TESTS[[j]]$result) 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /tests/testthat/test-constraints.checkMinLength.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | 6 | context("constraints.checkMinLength") 7 | 8 | # Constants 9 | TESTS <- list( 10 | 11 | list( 0, list(1), TRUE), 12 | 13 | list( 1, list(1), TRUE), 14 | 15 | list( 2, list(1), FALSE), 16 | 17 | list( 2, NULL, TRUE) 18 | 19 | ) 20 | 21 | # Tests 22 | 23 | foreach(j = seq_along(TESTS) ) %do% { 24 | 25 | TESTS[[j]] <- setNames(TESTS[[j]], c("constraint", "value", "result")) 26 | 27 | test_that(str_interp('constraint "${TESTS[[j]]$constraint}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 28 | 29 | expect_equal(constraints.checkMinLength(TESTS[[j]]$constraint, TESTS[[j]]$value), TESTS[[j]]$result) 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /tests/testthat/test-constraints.checkMinimum.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | 6 | context("constraints.checkMinimum") 7 | 8 | # Constants 9 | TESTS <- list( 10 | 11 | list( 0, 1, TRUE), 12 | 13 | list( 1, 1, TRUE), 14 | 15 | list( 2, 1, FALSE), 16 | 17 | list( 2, NULL, TRUE) 18 | 19 | ) 20 | 21 | # Tests 22 | 23 | foreach(j = seq_along(TESTS) ) %do% { 24 | 25 | TESTS[[j]] <- setNames(TESTS[[j]], c("constraint", "value", "result")) 26 | 27 | test_that(str_interp('constraint "${TESTS[[j]]$constraint}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 28 | 29 | expect_equal(constraints.checkMinimum(TESTS[[j]]$constraint, TESTS[[j]]$value), TESTS[[j]]$result) 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /tests/testthat/test-constraints.checkPattern.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | 6 | context("constraints.checkPattern") 7 | 8 | # Constants 9 | 10 | TESTS <- list( 11 | 12 | list('^test$', 'test', TRUE), 13 | 14 | list('^test$', 'TEST', FALSE), 15 | 16 | list('^test$', NULL, TRUE) 17 | 18 | ) 19 | 20 | # Tests 21 | 22 | foreach(j = seq_along(TESTS) ) %do% { 23 | 24 | TESTS[[j]] <- setNames(TESTS[[j]], c("constraint", "value", "result")) 25 | 26 | test_that(str_interp('constraint "${TESTS[[j]]$constraint}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 27 | 28 | expect_equal(constraints.checkPattern(TESTS[[j]]$constraint, TESTS[[j]]$value), TESTS[[j]]$result) 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /tests/testthat/test-constraints.checkRequired.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | 6 | context("constraints.checkRequired") 7 | 8 | # Constants 9 | 10 | TESTS <- list( 11 | 12 | list(FALSE, 1, TRUE), 13 | 14 | list(TRUE, 0, TRUE), 15 | 16 | list(TRUE, NULL, FALSE), 17 | 18 | list(TRUE, "undefined", FALSE) 19 | 20 | ) 21 | 22 | # Tests 23 | 24 | foreach(j = seq_along(TESTS) ) %do% { 25 | 26 | TESTS[[j]] <- setNames(TESTS[[j]], c("constraint", "value", "result")) 27 | 28 | test_that(str_interp('constraint "${TESTS[[j]]$constraint}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 29 | 30 | expect_equal(constraints.checkRequired(TESTS[[j]]$constraint, TESTS[[j]]$value), TESTS[[j]]$result) 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /tests/testthat/test-constraints.checkUnique.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | 6 | context("constraints.checkUnique") 7 | 8 | # Constants 9 | 10 | TESTS <- list( 11 | 12 | list(FALSE, "any", TRUE), 13 | 14 | list(TRUE, "any", TRUE), 15 | 16 | list(TRUE, "other", TRUE) 17 | 18 | ) 19 | 20 | # Tests 21 | 22 | foreach(j = seq_along(TESTS) ) %do% { 23 | 24 | TESTS[[j]] <- setNames(TESTS[[j]], c("constraint", "value", "result")) 25 | 26 | test_that(str_interp('constraint "${TESTS[[j]]$constraint}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 27 | 28 | expect_equal(constraints.checkUnique(TESTS[[j]]$constraint, TESTS[[j]]$value), TESTS[[j]]$result) 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /tests/testthat/test-errors.R: -------------------------------------------------------------------------------- 1 | library(tableschema.r) 2 | library(testthat) 3 | 4 | # Tests 5 | 6 | context("TableSchemaError") 7 | 8 | 9 | test_that('should work with one error', { 10 | error <- TableSchemaError$new('message') 11 | expect_equal(error$message, 'message') 12 | expect_equal(error$multiple, FALSE) 13 | expect_equal(error$errors, list()) 14 | }) 15 | 16 | test_that('should work with multiple errors', { 17 | errors <- list(Error = 'error1', Error = 'error2') 18 | error <- TableSchemaError$new('message', errors) 19 | expect_equal(error$message, 'message') 20 | expect_equal(error$multiple, TRUE) 21 | expect_equal(length(error$errors), 2) 22 | expect_equal(error$errors[[1]], 'error1') 23 | expect_equal(error$errors[[2]], 'error2') 24 | }) 25 | 26 | test_that('should be catchable as a normal error', { 27 | 28 | error <- withCallingHandlers( 29 | 30 | tryCatch( 31 | TableSchemaError$new('message'), 32 | error=function(e) { 33 | err <<- e 34 | NULL 35 | }), 36 | warning=function(w) { 37 | warn <<- w 38 | invokeRestart("muffleWarning") 39 | }) 40 | 41 | expect_equal(error$message, 'message') 42 | expect_true(inherits(error,"TableSchemaError")) 43 | }) 44 | 45 | -------------------------------------------------------------------------------- /tests/testthat/test-helpers.R: -------------------------------------------------------------------------------- 1 | library(tableschema.r) 2 | library(testthat) 3 | library(future) 4 | 5 | context("helpers") 6 | 7 | test_that('test', { 8 | 9 | expect_equal(future::value(helpers.retrieveDescriptor(descriptor = '{"this": "that", "other": ["thing"]}')), 10 | '{"this": "that", "other": ["thing"]}') 11 | }) 12 | 13 | test_that('test', { 14 | expect_equal(future::value(helpers.retrieveDescriptor(descriptor = '[{"this": "that", "other": ["thing"]}]')), 15 | '[{"this": "that", "other": ["thing"]}]') 16 | }) 17 | 18 | test_that('test', { 19 | expect_equal(future::value(helpers.retrieveDescriptor(descriptor = 'inst/extdata/schema_valid_full.json')), 20 | readLines('https://raw.githubusercontent.com/frictionlessdata/tableschema-py/master/data/schema_valid_full.json')) 21 | }) 22 | 23 | test_that('test', { 24 | expect_equal(class(future::value(helpers.retrieveDescriptor(descriptor = 'https://raw.githubusercontent.com/frictionlessdata/tableschema-py/master/data/schema_valid_full.json'))), 25 | "character") 26 | }) 27 | 28 | test_that('test', { 29 | expect_error(future::value(helpers.retrieveDescriptor(descriptor = 'https://raw.githubusercontent.com/frictionlessdata/tableschema-py/master/data/'))) 30 | }) 31 | 32 | test_that('test', { 33 | expect_error(future::value(helpers.retrieveDescriptor(descriptor = 'inst/extdata/data.infer.csv'))) 34 | }) 35 | 36 | test_that('test', { 37 | expect_error(is.uri(20)) 38 | }) 39 | 40 | test_that('test', { 41 | expect_error(is.uuid(20)) 42 | }) 43 | 44 | test_that('test', { 45 | expect_error(is.valid(20)) 46 | }) 47 | 48 | SCHEMA <- '{ 49 | "fields": [ 50 | {"name": "id", "type": "string", "constraints": {"required": true}}, 51 | {"name": "height", "type": "number"}, 52 | {"name": "age", "type": "integer"}, 53 | {"name": "name", "type": "string", "constraints": {"required": true}}, 54 | {"name": "occupation", "type": "string"} 55 | ] 56 | }' 57 | 58 | test_that('test', { 59 | expect_true(is.valid(SCHEMA)$valid) 60 | }) 61 | 62 | test_that("write json", { 63 | def <- Schema.load(SCHEMA) 64 | schema <- future::value(def) 65 | jsonchar <- helpers.from.list.to.json(schema$descriptor) 66 | write_json(jsonchar, "inst/extdata/jsonchar.json") 67 | 68 | expect_true(file.exists("inst/extdata/jsonchar.json")) 69 | }) 70 | -------------------------------------------------------------------------------- /tests/testthat/test-infer.R: -------------------------------------------------------------------------------- 1 | library(tableschema.r) 2 | library(testthat) 3 | 4 | 5 | context("infer") 6 | 7 | 8 | test_that("produce schema from a generic .csv", { 9 | 10 | source <- 'inst/extdata/data_infer.csv' 11 | descriptor <- infer(source) 12 | expect_equivalent(descriptor$fields, list( 13 | list(name = 'id', type = 'integer', format = 'default'), 14 | list(name = 'age', type = 'integer', format = 'default'), 15 | list(name = 'name', type = 'string', format = 'default') 16 | )) 17 | }) 18 | 19 | test_that("produce schema from a generic .csv UTF-8 encoded", { 20 | 21 | source <- 'inst/extdata/data_infer_utf8.csv' 22 | descriptor <- infer(source) 23 | expect_equivalent(descriptor$fields, list( 24 | list(name = 'id', type = 'integer', format = 'default'), 25 | list(name = 'age', type = 'integer', format = 'default'), 26 | list(name = 'name', type = 'string', format = 'default') 27 | )) 28 | }) 29 | 30 | test_that("respect row limit parameter", { 31 | 32 | source <- 'inst/extdata/data_infer_row_limit.csv' 33 | descriptor <- infer(source, options = list(limit = 4)) 34 | expect_equivalent(descriptor$fields, list( 35 | list(name = 'id', type = 'integer', format = 'default'), 36 | list(name = 'age', type = 'integer', format = 'default'), 37 | list(name = 'name', type = 'string', format = 'default') 38 | )) 39 | }) 40 | 41 | test_that('could infer formats', { 42 | descriptor <- infer('inst/extdata/data_infer_formats.csv') 43 | expect_equivalent(descriptor$fields, 44 | helpers.from.json.to.list( 45 | '[{"name": "id", "type": "integer", "format": "default"}, 46 | {"name": "capital", "type": "string", "format": "default"}, 47 | {"name": "url", "type": "string", "format": "default"}]')) 48 | }) 49 | -------------------------------------------------------------------------------- /tests/testthat/test-profile.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | library(jsonlite) 6 | 7 | context("profile") 8 | 9 | 10 | test_that("table-schema is up-to-date", { 11 | # res = jsonlite::toJSON(jsonlite::fromJSON( system.file(stringr::str_interp("profiles/tableschema.json"), package = "tableschema.r"))) 12 | 13 | res <- jsonlite::toJSON(jsonlite::fromJSON('https://specs.frictionlessdata.io/schemas/table-schema.json',simplifyVector = TRUE)) 14 | profile <- Profile.load('tableschema') 15 | 16 | expect_equal(class(profile$jsonschema),"json") 17 | expect_equal(profile$name, "table-schema") 18 | expect_type(res,"character") 19 | expect_type(profile$jsonschema,"character") 20 | expect_true(profile$validate(readLines('inst/extdata/schema.json'))$valid) 21 | expect_true(profile$validate('{"fields": [{"name": "year", "format": "%Y", "type": "date"}]}')$valid) 22 | expect_false(profile$validate('{ 23 | "fields": [{"name": "name"}], 24 | "primaryKey": ["name"], 25 | "foreignKeys": [{ 26 | "fields": ["parent_id"], 27 | "reference": {"resource": "resource", "fields": ["id"]} 28 | }] 29 | }')$valid) 30 | expect_equal(profile$name, "table-schema") 31 | }) 32 | 33 | # 34 | test_that("table-schema is up-to-date", { 35 | profile <- Profile.load('geojson') 36 | expect_silent(profile$jsonschema) 37 | }) 38 | 39 | test_that("error", { 40 | expect_error(Profile.load('geo-json')) 41 | expect_error(Profile.load('')) 42 | }) 43 | 44 | test_that("url profile", { 45 | expect_equal(Profile.load('tableschema')$jsonschema, 46 | Profile.load('https://raw.githubusercontent.com/frictionlessdata/tableschema-r/master/inst/profiles/tableschema.json')$jsonschema) 47 | }) 48 | 49 | test_that("local file profile", { 50 | expect_equal(Profile.load('inst/profiles/tableschema.json')$jsonschema, 51 | Profile.load('https://raw.githubusercontent.com/frictionlessdata/tableschema-r/master/inst/profiles/tableschema.json')$jsonschema) 52 | expect_equal(Profile.load('inst/profiles/tableschema.json')$jsonschema, Profile.load('tableschema')$jsonschema) 53 | }) 54 | -------------------------------------------------------------------------------- /tests/testthat/test-types.castAny.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | 6 | context("types.castAny") 7 | 8 | # Constants 9 | 10 | TESTS <- list( 11 | 12 | list("default", 1, 1), 13 | 14 | list("default", "1", "1"), 15 | 16 | list("default", "3.14", "3.14"), 17 | 18 | list("default", TRUE, TRUE), 19 | 20 | list("default", "", "") 21 | 22 | ) 23 | 24 | # Tests 25 | 26 | foreach(j = seq_along(TESTS) ) %do% { 27 | 28 | TESTS[[j]] <- setNames(TESTS[[j]], c("format", "value", "result")) 29 | 30 | test_that(str_interp('format "${TESTS[[j]]$format}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 31 | 32 | expect_equal(types.castAny(TESTS[[j]]$format, TESTS[[j]]$value), TESTS[[j]]$result) 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /tests/testthat/test-types.castArray.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | library(config) 6 | 7 | context("types.castArray") 8 | 9 | # Constants 10 | TESTS <- list( 11 | list('default', list(), list()), 12 | list('default', "[]", list()), 13 | list('default', list('key', 'value'), list('key', 'value')), 14 | list('default', '["key", "value"]', list('key', 'value')), 15 | list('default', 'string', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 16 | list('default', 1, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 17 | list('default', '3.14', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 18 | list('default', '', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 19 | ) 20 | 21 | # Tests 22 | 23 | foreach(j = seq_along(TESTS) ) %do% { 24 | 25 | TESTS[[j]] <- setNames(TESTS[[j]], c("format", "value", "result")) 26 | 27 | test_that(str_interp('format "${TESTS[[j]]$format}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 28 | 29 | expect_equal(types.castArray(TESTS[[j]]$format, TESTS[[j]]$value), TESTS[[j]]$result) 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /tests/testthat/test-types.castBoolean.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | library(config) 6 | 7 | context("types.castBoolean") 8 | 9 | # Constants 10 | 11 | TESTS <- list( 12 | 13 | list("default", TRUE, TRUE, {} ), 14 | list("default", "true", TRUE, {} ), 15 | list("default", "True", TRUE, {} ), 16 | list("default", "TRUE", TRUE, {} ), 17 | list("default", "1", TRUE,{} ), 18 | list("default", "yes", TRUE, list(trueValues = list("yes")) ), 19 | list("default", "Y", TRUE, list(trueValues = list("Y")) ), 20 | 21 | list("default", FALSE, FALSE, {} ), 22 | list("default", "false", FALSE, {} ), 23 | list("default", "False", FALSE, {} ), 24 | list("default", "FALSE", FALSE, {} ), 25 | list("default", "0", FALSE, {}), 26 | list("default", "no", FALSE, list(falseValues = list("no")) ), 27 | list("default", "N", FALSE, list(falseValues = list("N")) ), 28 | 29 | list("default", "YES", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 30 | list("default", "Yes", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 31 | list("default", "yes", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 32 | list("default", "y", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 33 | list("default", "t", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 34 | list("default", "f", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 35 | list("default", "no", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 36 | list("default", "n", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 37 | list("default", "NO", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 38 | list("default", "No", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 39 | 40 | list("default", "N", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), list(falseValues = list("n"))), 41 | list("default", "Y", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), list(falseValues = list("y"))), 42 | 43 | list("default", 0, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 44 | list("default", 1, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 45 | list("default", "3.14", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 46 | list("default", "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ) 47 | ) 48 | 49 | # Tests 50 | 51 | foreach(j = seq_along(TESTS) ) %do% { 52 | 53 | TESTS[[j]] <- setNames(TESTS[[j]], c("format", "value", "result", "options")) 54 | 55 | test_that(str_interp('format "${TESTS[[j]]$format}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 56 | 57 | expect_equal(types.castBoolean(TESTS[[j]]$format, TESTS[[j]]$value, TESTS[[j]]$options), TESTS[[j]]$result) 58 | }) 59 | } 60 | -------------------------------------------------------------------------------- /tests/testthat/test-types.castDate.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | library(config) 6 | 7 | context("types.castDate") 8 | 9 | # Constants 10 | 11 | TESTS <- list( 12 | 13 | list("default", as.Date("2019-1-1"), as.Date("2019-1-1")), 14 | 15 | list("default", "2019-01-01", as.Date("2019-1-1")), 16 | 17 | list("default", "10th Jan 1969", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 18 | 19 | list("default", "invalid", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 20 | 21 | list("default", TRUE, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 22 | 23 | list("default", "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 24 | 25 | list("any", as.Date("2019-1-1"), as.Date("2019-1-1")), 26 | 27 | list("any", "2019-01-01", as.Date("2019-1-1")), 28 | 29 | #list ("any", "10th Jan 1969", as.Date("1969-1-10")), 30 | 31 | list("any", "10th Jan nineteen sixty nine", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 32 | 33 | list("any", "invalid", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 34 | 35 | list("any", TRUE, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 36 | 37 | list("any", "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 38 | 39 | list("%d/%m/%y", as.Date("2019-1-1"), as.Date("2019-1-1")), 40 | 41 | list("%d/%m/%y", "21/11/06", as.Date("2006-11-21")), 42 | 43 | list("%y/%m/%d", "21/11/06 16:30", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 44 | 45 | list("%d/%m/%y", "invalid", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 46 | 47 | list("%d/%m/%y", TRUE, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 48 | 49 | list("%d/%m/%y", "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 50 | 51 | list("invalid", "21/11/06 16:30", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 52 | 53 | list("invalid", as.Date("2019-1-1"), as.Date("2019-1-1")), 54 | 55 | # Deprecated 56 | list("fmt:%d/%m/%y", as.Date("2019-1-1"), as.Date("2019-1-1")), 57 | 58 | list("fmt:%d/%m/%y", "21/11/06", as.Date("2006-11-21")), 59 | 60 | list("fmt:%y/%m/%d", "21/11/06 16:30", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 61 | 62 | list("fmt:%d/%m/%y", "invalid", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 63 | 64 | list("fmt:%d/%m/%y", TRUE, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 65 | 66 | list("fmt:%d/%m/%y", "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 67 | 68 | ) 69 | 70 | 71 | # Tests 72 | 73 | foreach(j = seq_along(TESTS) ) %do% { 74 | 75 | TESTS[[j]] <- setNames(TESTS[[j]], c("format", "value", "result")) 76 | 77 | test_that(str_interp('format "${TESTS[[j]]$format}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 78 | 79 | expect_equal(types.castDate(TESTS[[j]]$format, TESTS[[j]]$value), TESTS[[j]]$result) 80 | }) 81 | } 82 | -------------------------------------------------------------------------------- /tests/testthat/test-types.castDatetime.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | library(lubridate) 6 | library(config) 7 | 8 | context("types.castDatetime") 9 | 10 | datetime <- function(year, month, day, hour=0, minute=0, second=0){ 11 | 12 | return(lubridate::as_date(lubridate::make_datetime(year, month, day, hour, minute, second,tz = "UTC"))) 13 | } 14 | 15 | # Constants 16 | 17 | TESTS <- list( 18 | 19 | list("default", datetime(2014, 1, 1, 6), datetime(2014, 1, 1, 6)), 20 | 21 | list("default", "2014-01-01T06:00:00Z", lubridate::make_datetime(2014, 1, 1, 6)), 22 | 23 | list("default", "Mon 1st Jan 2014 9 am", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 24 | 25 | list("default", "invalid", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 26 | 27 | list("default", TRUE, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 28 | 29 | list("default", "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 30 | 31 | list("any", datetime(2014, 1, 1, 6), datetime(2014, 1, 1, 6)), 32 | 33 | #["any", "10th Jan 1969 9 am", datetime(1969, 1, 10, 9)), 34 | 35 | list("any", "invalid", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 36 | 37 | list("any", TRUE, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 38 | 39 | list("any", "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 40 | 41 | list("%y/%m/%d %H:%M", datetime(2006, 11, 21, 16, 30), datetime(2006, 11, 21, 16, 30)), 42 | 43 | list("%d/%m/%y %H:%M", "21/11/06 16:30", lubridate::make_datetime(2006, 11, 21, 16, 30)), 44 | 45 | list("%H:%M %d/%m/%y", "21/11/06 16:30", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 46 | 47 | list("%d/%m/%y %H:%M", "invalid", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 48 | 49 | list("%d/%m/%y %H:%M", TRUE, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 50 | 51 | list("%d/%m/%y %H:%M", "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 52 | 53 | list("invalid", "21/11/06 16:30", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 54 | 55 | # Deprecated 56 | list("fmt:%d/%m/%y %H:%M", datetime(2006, 11, 21, 16, 30), datetime(2006, 11, 21, 16, 30)), 57 | 58 | list("fmt:%d/%m/%y %H:%M", "21/11/06 16:30", lubridate::make_datetime(2006, 11, 21, 16, 30)), 59 | 60 | list("fmt:%H:%M %d/%m/%y", "21/11/06 16:30", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 61 | 62 | list("fmt:%d/%m/%y %H:%M", "invalid", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 63 | 64 | list("fmt:%d/%m/%y %H:%M", TRUE, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 65 | 66 | list("fmt:%d/%m/%y %H:%M", "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 67 | 68 | ) 69 | 70 | # Tests 71 | 72 | foreach(j = seq_along(TESTS) ) %do% { 73 | 74 | TESTS[[j]] <- setNames(TESTS[[j]], c("format", "value", "result")) 75 | 76 | test_that(str_interp('format "${TESTS[[j]]$format}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 77 | 78 | expect_equal(types.castDatetime(TESTS[[j]]$format, TESTS[[j]]$value), TESTS[[j]]$result) 79 | }) 80 | } 81 | -------------------------------------------------------------------------------- /tests/testthat/test-types.castDuration.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | library(config) 6 | 7 | context("types.castDuration") 8 | 9 | # Constants 10 | 11 | TESTS <- list( 12 | 13 | list("default", durations(years = 1), durations(years = 1)), 14 | list("default", "P1Y10M3DT5H11M7S", durations(years = 1, months = 10, days = 3, hours = 5, minutes = 11, seconds = 7)), 15 | #list("default", "P1Y", durations({years: 1})), 16 | #list("default", "P1M", durations(months = 1)), 17 | list("default", "P1M1Y", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 18 | list("default", "P-1Y", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 19 | list("default", "year", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 20 | list("default", TRUE, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 21 | list("default", FALSE, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 22 | list("default", 1, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 23 | list("default", "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 24 | list("default", list(), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 25 | list("default", {}, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 26 | 27 | ) 28 | 29 | # Tests 30 | 31 | foreach(j = seq_along(TESTS) ) %do% { 32 | 33 | TESTS[[j]] <- setNames(TESTS[[j]], c("format", "value", "result")) 34 | 35 | test_that(str_interp('format "${TESTS[[j]]$format}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 36 | 37 | expect_equal(types.castDuration(TESTS[[j]]$format, TESTS[[j]]$value), TESTS[[j]]$result) 38 | }) 39 | } 40 | -------------------------------------------------------------------------------- /tests/testthat/test-types.castGeojson.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | library(config) 6 | 7 | context("types.castGeojson") 8 | 9 | # Constants 10 | 11 | TESTS <- list( 12 | 13 | ## list('default', 14 | ## {'properties': {'Ã': 'Ã'}, 'type': 'Feature', 'geometry': NULL}, 15 | ## {'properties': {'Ã': 'Ã'}, 'type': 'Feature', 'geometry': NULL} ), 16 | 17 | ## list('default', 18 | ## '{"geometry": null, "type": "Feature", "properties": {"\\u00c3": "\\u00c3"}}', 19 | ## {'properties': {'Ã': 'Ã'}, 'type': 'Feature', 'geometry': NULL} ), 20 | 21 | list('default', "{'coordinates': [0, 0, 0], 'type': 'Point'}", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")) ), 22 | list('default', 'string', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")) ), 23 | list('default', 1, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")) ), 24 | list('default', '3.14', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")) ), 25 | list('default', '', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")) ), 26 | list('default', {}, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")) ), 27 | list('default', '{}', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")) ), 28 | 29 | #list('topojson', "{'type': 'LineString', 'arcs': [42]}","{'type': 'LineString', 'arcs': [42]}" ), 30 | 31 | #list('topojson', '{"type": "LineString", "arcs": [42]}',{'type': 'LineString', 'arcs': [42]} ), 32 | 33 | list('topojson', list("arcs" = list(42)), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 34 | list('topojson', 'string', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 35 | list('topojson', 1, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 36 | list('topojson', '3.14', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 37 | list('topojson', '', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")) ) 38 | ) 39 | 40 | # Tests 41 | 42 | foreach(j = seq_along(TESTS) ) %do% { 43 | 44 | TESTS[[j]] <- setNames(TESTS[[j]], c("format", "value", "result")) 45 | 46 | test_that(str_interp('format "${TESTS[[j]]$format}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 47 | 48 | expect_equal(types.castGeojson(TESTS[[j]]$format, TESTS[[j]]$value), TESTS[[j]]$result) 49 | }) 50 | } 51 | -------------------------------------------------------------------------------- /tests/testthat/test-types.castGeopoint.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | library(config) 6 | 7 | context("types.castGeopoint") 8 | 9 | # Constants 10 | 11 | TESTS <- list( 12 | list('default', list(180, 90), list(180, 90) ), 13 | list('default', '180,90', list(180, 90) ), 14 | list('default', '180, -90', list(180, -90) ), 15 | list('default', list(lon = 180, lat = 90), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")) ), 16 | list('default', list(181,90), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")) ), 17 | list('default', '0,91', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")) ), 18 | list('default', 'string', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")) ), 19 | list('default', 1, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")) ), 20 | list('default', '3.14', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")) ), 21 | list('default', '', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")) ), 22 | list('array', list(180, 90), list(180, 90) ), 23 | list('array', '[180, -90]', list(180, -90)), 24 | list('array', list(lon = 180, lat = 90), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 25 | list('array', list(181, 90), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 26 | list('array', list(0, 91), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 27 | 28 | list('array', '180,90', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 29 | list('array', 'string', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 30 | list('array', 1, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 31 | list('array', '3.14', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 32 | list('array', '', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 33 | 34 | list('object', list(lon = 180, lat = 90), list(180, 90)), 35 | list('object', '{"lon": 180, "lat": 90}', list(180, 90)), 36 | #list('object', '[180, -90]', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 37 | 38 | list('object', "{'lon': 181, 'lat': 90}", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 39 | list('object', "{'lon': 180, 'lat': -91}", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 40 | 41 | #list('object', list(180, -90), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 42 | list('object', '180,90', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 43 | list('object', 'string', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 44 | list('object', 1, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 45 | list('object', '3.14', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 46 | list('object', '', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 47 | ) 48 | 49 | # Tests 50 | 51 | foreach(j = seq_along(TESTS) ) %do% { 52 | 53 | TESTS[[j]] <- setNames(TESTS[[j]], c("format", "value", "result")) 54 | 55 | test_that(str_interp('format "${TESTS[[j]]$format}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 56 | 57 | expect_equal(types.castGeopoint(TESTS[[j]]$format, TESTS[[j]]$value), TESTS[[j]]$result) 58 | }) 59 | } 60 | -------------------------------------------------------------------------------- /tests/testthat/test-types.castInteger.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | library(config) 6 | 7 | context("types.castInteger") 8 | 9 | # Constants 10 | 11 | TESTS <- list( 12 | list('default', 1, 1, {} ), 13 | list('default', '1', 1, {} ), 14 | list('default', '1$', 1, list(bareNumber = FALSE) ), 15 | list('default', 'ab1$', 1, list(bareNumber = FALSE) ), 16 | list('default', '3.14', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {}), 17 | list('default', '', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {}), 18 | list('default', 1.2, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {}), 19 | list('default', types.castInteger('default', list(1:5)), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {}) 20 | ) 21 | # Tests 22 | 23 | foreach(j = seq_along(TESTS) ) %do% { 24 | 25 | TESTS[[j]] <- setNames(TESTS[[j]], c("format", "value", "result","options")) 26 | 27 | test_that(str_interp('format "${TESTS[[j]]$format}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 28 | 29 | expect_equal(types.castInteger(TESTS[[j]]$format, TESTS[[j]]$value, TESTS[[j]]$options), TESTS[[j]]$result) 30 | }) 31 | } 32 | 33 | test_that('error at NULL values',{ 34 | expect_error(types.castInteger('default', NULL)) 35 | }) 36 | -------------------------------------------------------------------------------- /tests/testthat/test-types.castList.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | library(config) 6 | 7 | context("types.castList") 8 | 9 | # Constants 10 | TESTS <- list( 11 | list('default', list(), list()), 12 | list('default', "[]", list()), 13 | list('default', list('key', 'value'), list('key', 'value')), 14 | list('default', '["key", "value"]', list('key', 'value')), 15 | list('default', 'string', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 16 | list('default', 1, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 17 | list('default', '3.14', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 18 | list('default', '', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 19 | ) 20 | 21 | # Tests 22 | 23 | foreach(j = seq_along(TESTS) ) %do% { 24 | 25 | TESTS[[j]] <- setNames(TESTS[[j]], c("format", "value", "result")) 26 | 27 | test_that(str_interp('format "${TESTS[[j]]$format}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 28 | 29 | expect_equal(types.castList(TESTS[[j]]$format, TESTS[[j]]$value), TESTS[[j]]$result) 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /tests/testthat/test-types.castNumber.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | library(config) 6 | 7 | context("types.castNumber") 8 | 9 | # Constants 10 | 11 | TESTS <- list( 12 | list('default', 1, 1, {}), 13 | list('default', 1, 1, {}), 14 | list('default', 1.0, 1, {}), 15 | list('default', '1', 1, {}), 16 | list('default', '10.00', 10, {}), 17 | list('default', '10.50', 10.5, {}), 18 | list('default', '100%', 100, list(bareNumber = FALSE) ), 19 | list('default', '1000‰', 1000, list(bareNumber = FALSE) ), 20 | list('default', '-1000', -1000, {}), 21 | list('default', '1,000', 1000, list(groupChar = ',') ), 22 | list('default', '10,000.00', 10000, list(groupChar = ',') ), 23 | list('default', '10,000,000.50', 10000000.5, list(groupChar = ',') ), 24 | list('default', '10#000.00', 10000, list(groupChar = '#') ), 25 | list('default', '10#000#000.50', 10000000.5, list(groupChar = '#') ), 26 | list('default', '10.50', 10.5, list(groupChar = '#') ), 27 | list('default', '1#000', 1000, list(groupChar = '#') ), 28 | list('default', '10#000@00', 10000, list(groupChar = '#', decimalChar = '@') ), 29 | list('default', '10#000#000@50', 10000000.5, list(groupChar = '#', decimalChar = '@') ), 30 | list('default', '10@50', 10.5, list(groupChar = '#', decimalChar = '@') ), 31 | list('default', '1#000', 1000, list(groupChar = '#', decimalChar = '@') ), 32 | 33 | list('default', '10,000.00', 10000, list( groupChar = ',', bareNumber = FALSE) ), 34 | list('default', '10,000,000.00', 10000000, list(groupChar = ',', bareNumber = FALSE) ), 35 | list('default', '$10000.00', 10000, list(bareNumber = FALSE) ), 36 | list('default', ' 10,000.00 €', 10000, list(groupChar = ',', bareNumber = FALSE) ), 37 | list('default', '10 000,00', 10000, list(groupChar = ' ', decimalChar = ',') ), 38 | list('default', '10 000 000,00', 10000000, list(groupChar = ' ', decimalChar = ',') ), 39 | list('default', '10000,00 ₪', 10000, list('groupChar' = ' ', 'decimalChar' = ',', 'bareNumber' = FALSE)), 40 | list('default', ' 10 000,00 £', 10000, list( groupChar = ' ', decimalChar = ',', bareNumber = FALSE) ), 41 | list('default', '10,000a.00', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 42 | list('default', '10+000.00', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 43 | list('default', '$10:000.00', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 44 | list('default', 'string', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 45 | list('default', '', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {} ), 46 | list('default', NULL, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {}), 47 | list('default', list(1:3), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {}), 48 | list('default', "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {}), 49 | list('default', '1000000', 1000000, list( bareNumber = TRUE)), 50 | list('default', "100a", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r")), {}) 51 | 52 | ) 53 | 54 | # Tests 55 | 56 | foreach(j = seq_along(TESTS) ) %do% { 57 | 58 | TESTS[[j]] <- setNames(TESTS[[j]], c("format", "value", "result","options")) 59 | 60 | test_that(str_interp('format "${TESTS[[j]]$format}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 61 | 62 | expect_equal(types.castNumber(TESTS[[j]]$format, TESTS[[j]]$value, TESTS[[j]]$options), TESTS[[j]]$result) 63 | }) 64 | } 65 | -------------------------------------------------------------------------------- /tests/testthat/test-types.castObject.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(config) 5 | library(foreach) 6 | 7 | context("types.castObject") 8 | 9 | # Constants 10 | 11 | TESTS <- list( 12 | list('default', list(), list()), 13 | list('default', '{}', helpers.from.json.to.list('{}')), 14 | list('default', '{"key": "value"}', list('key' = 'value')), 15 | list('default', '["key", "value"]', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 16 | list('default', 'string', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 17 | list('default', 1, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 18 | list('default', '3.14', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 19 | list('default', '', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 20 | list('default', matrix(1:4, nrow = 2), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 21 | list('default', NULL, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 22 | list('default', '[["id", "name"],["1", "ab"]]', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 23 | ) 24 | 25 | # Tests 26 | 27 | foreach(j = seq_along(TESTS) ) %do% { 28 | 29 | TESTS[[j]] <- setNames(TESTS[[j]], c("format", "value", "result")) 30 | 31 | test_that(str_interp('format "${TESTS[[j]]$format}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 32 | 33 | expect_equal(types.castObject(TESTS[[j]]$format, TESTS[[j]]$value), TESTS[[j]]$result) 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /tests/testthat/test-types.castString.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | library(config) 6 | 7 | context("types.castString") 8 | 9 | # Constants 10 | 11 | TESTS <- list( 12 | list("default", "string", "string"), 13 | list("default", "", ""), 14 | list("default", 0, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 15 | 16 | list("uri", "http://google.com", "http://google.com"), 17 | list("uri", "://no-scheme.test", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 18 | list("uri", "string", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 19 | list("uri", "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 20 | list("uri", 0, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 21 | 22 | list("email", "name@gmail.com", "name@gmail.com"), 23 | list("email", "http://google.com", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 24 | list("email", "string", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 25 | list("email", "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 26 | list("email", 0, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 27 | ) 28 | 29 | # Tests 30 | 31 | foreach(j = seq_along(TESTS) ) %do% { 32 | 33 | TESTS[[j]] <- setNames(TESTS[[j]], c("format", "value", "result")) 34 | 35 | test_that(str_interp('format "${TESTS[[j]]$format}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 36 | 37 | expect_equal(types.castString(TESTS[[j]]$format, TESTS[[j]]$value), TESTS[[j]]$result) 38 | }) 39 | } 40 | 41 | 42 | TESTS2 <- list( 43 | 44 | list("uuid", '95ecc380-afe9-11e4-9b6c-751b66dd541e', '95ecc380-afe9-11e4-9b6c-751b66dd541e'), 45 | list("uuid", '0a7b330a-a736-35ea-8f7f-feaf019cdc00', '0a7b330a-a736-35ea-8f7f-feaf019cdc00'), 46 | list("uuid", '0a7b330a-a736-35ea-8f7f-feaf019cdc', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 47 | list("uuid", "string", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 48 | list("uuid", "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 49 | list("uuid", 0, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 50 | 51 | 52 | list("binary", "YXN1cmUu", "YXN1cmUu"), 53 | list("binary", "c3VyZS4=", "c3VyZS4="), 54 | list("binary", "dGVzdA==", "dGVzdA=="), 55 | list("binary", "string", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 56 | list("binary", "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 57 | list("binary", 0, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 58 | ) 59 | 60 | # Tests 61 | 62 | foreach(j = seq_along(TESTS2) ) %do% { 63 | 64 | TESTS2[[j]] <- setNames(TESTS2[[j]], c("format", "value", "result")) 65 | 66 | test_that(str_interp('format "${TESTS2[[j]]$format}" should check "${TESTS2[[j]]$value}" as "${TESTS2[[j]]$result}"'), { 67 | 68 | expect_equal(types.castString(TESTS2[[j]]$format, TESTS2[[j]]$value), TESTS2[[j]]$result) 69 | }) 70 | } -------------------------------------------------------------------------------- /tests/testthat/test-types.castTime.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | library(lubridate) 6 | library(config) 7 | 8 | context("types.castTime") 9 | 10 | Time <- function(hour, minute=0, second=0) { 11 | value <- lubridate::as_datetime(lubridate::make_datetime(0, 0, 1, hour, minute, second,tz = "UTC")) 12 | unlist(strsplit(as.character(value), " "))[[2]] 13 | } 14 | 15 | # Constants 16 | 17 | TESTS <- list( 18 | 19 | list('default', Time(6), Time(6)), 20 | list('default', '06:00:00', Time(6)), 21 | list('default', '09:00', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 22 | list('default', '3 am', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 23 | list('default', '3.00', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 24 | list('default', 'invalid', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 25 | list('default', TRUE, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 26 | list('default', '', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 27 | list('any', Time(6), Time(6)), 28 | ### list(/ ['any', '06:00:00', Time(6)), 29 | ### list(/ ['any', '3:00 am', Time(3)), 30 | list('any', 'some night', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 31 | list('any', 'invalid', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 32 | list('any', TRUE, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 33 | list('any', '', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 34 | list('%H:%M', Time(6), Time(6)), 35 | # list('%H:%M', '06:00', Time(6)), 36 | ### list(/ ['%M:%H', '06:50', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 37 | # list('%H:%M', '3:00 am', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 38 | list('%H:%M', 'some night', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 39 | list('%H:%M', 'invalid', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 40 | list('%H:%M', TRUE, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 41 | list('%H:%M', '', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 42 | list('invalid', '', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 43 | ### list(/ Deprecat)d 44 | # list('fmt:%H:%M', Time(6), Time(6)), 45 | # list('fmt:%H:%M', '06:00', Time(6)), 46 | # list(/ ['fmt:%M:%H', '06:50', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 47 | list('fmt:%M:%H', '06:50', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 48 | # list(/ ['fmt:%M:%H', '06:50', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 49 | # list('fmt:%H:%M', '3:00 am', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 50 | list('fmt:%H:%M', 'some night', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 51 | list('fmt:%H:%M', 'invalid', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 52 | list('fmt:%H:%M', TRUE, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 53 | list('fmt:%H:%M', '', config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 54 | ) 55 | 56 | # Tests 57 | 58 | foreach(j = seq_along(TESTS) ) %do% { 59 | 60 | TESTS[[j]] <- setNames(TESTS[[j]], c("format", "value", "result")) 61 | 62 | test_that(str_interp('format "${TESTS[[j]]$format}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 63 | 64 | expect_equal(types.castTime(TESTS[[j]]$format, TESTS[[j]]$value), TESTS[[j]]$result) 65 | }) 66 | } 67 | -------------------------------------------------------------------------------- /tests/testthat/test-types.castYear.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | library(config) 6 | 7 | context("types.castYear") 8 | 9 | # Constants 10 | 11 | TESTS <- list( 12 | 13 | list("default", 2000, 2000), 14 | list("default", "2000", 2000), 15 | list("default", -2000, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 16 | list("default", 20000, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 17 | list("default", "20000000", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 18 | list("default", "3.14", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 19 | list("default", "2000a", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 20 | list("default", "200a", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 21 | list("default", matrix(c("1","2"),nrow = 1), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 22 | list("default", "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 23 | list("default", list(2000), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 24 | 25 | ) 26 | 27 | # Tests 28 | 29 | foreach(j = seq_along(TESTS) ) %do% { 30 | 31 | TESTS[[j]] <- setNames(TESTS[[j]], c("format", "value", "result")) 32 | 33 | test_that(str_interp('format "${TESTS[[j]]$format}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 34 | 35 | expect_equal(types.castYear(TESTS[[j]]$format, TESTS[[j]]$value), TESTS[[j]]$result) 36 | }) 37 | } 38 | -------------------------------------------------------------------------------- /tests/testthat/test-types.castYearmonth.R: -------------------------------------------------------------------------------- 1 | library(stringr) 2 | library(tableschema.r) 3 | library(testthat) 4 | library(foreach) 5 | library(config) 6 | 7 | context("types.castYearmonth") 8 | 9 | 10 | # Constants 11 | 12 | TESTS <- list( 13 | 14 | list("default", list(2000, 10), list(2000, 10)), 15 | 16 | list("default", "2000-10", list(2000, 10)), 17 | 18 | list("default", "2000/10", list(2000, 10)), 19 | 20 | list("default", list(2000, 10, 20), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 21 | 22 | list("default", "2000-13-20", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 23 | 24 | list("default", "2000-13", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 25 | 26 | list("default", "2000/13", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 27 | 28 | list("default", "2000/-1", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 29 | 30 | list("default", "2000-0", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 31 | 32 | list("default", "13", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 33 | 34 | list("default", -10, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 35 | 36 | list("default", 20, config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 37 | 38 | list("default", list(2000), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 39 | 40 | list("default", list(2000, -10), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 41 | 42 | list("default", list(2000, 13), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 43 | 44 | list("default", c(20,11), config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 45 | 46 | list("default", "3.14", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 47 | 48 | list("default", "abc", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))), 49 | 50 | list("default", "", config::get("ERROR", file = system.file("config/config.yml", package = "tableschema.r"))) 51 | 52 | ) 53 | 54 | # Tests 55 | 56 | foreach(j = seq_along(TESTS) ) %do% { 57 | 58 | TESTS[[j]] <- setNames(TESTS[[j]], c("format", "value", "result")) 59 | 60 | test_that(str_interp('format "${TESTS[[j]]$format}" should check "${TESTS[[j]]$value}" as "${TESTS[[j]]$result}"'), { 61 | 62 | expect_equal( 63 | types.castYearmonth(TESTS[[j]]$format, 64 | TESTS[[j]]$value), 65 | TESTS[[j]]$result) 66 | }) 67 | } 68 | --------------------------------------------------------------------------------