From 5ae5ab0f5f9715e55ec24414fdb2345ecf29fc0d Mon Sep 17 00:00:00 2001 From: "Zachary P. Christensen" Date: Thu, 6 Jul 2023 22:27:39 -0400 Subject: [PATCH 01/26] dimension metadata support --- src/DataAPI.jl | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ test/runtests.jl | 77 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 167 insertions(+), 1 deletion(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index da0da0e..fd4149f 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -515,6 +515,97 @@ Throw an error if `x` does not support metadata deletion for column `col`. """ function emptycolmetadata! end +""" + dimmetadatasupport(T::Type, dim::Int) + +Return a `NamedTuple{(:read, :write), Tuple{Bool, Bool}}` indicating whether +values of type `T` support metadata correspond to dimension `dim`. + +The `read` field indicates whether reading metadata with the [`dimmetadata`](@ref) +and [`dimmetadatakeys`]](@ref) functions is supported. + +The `write` field indicates whether modifying metadata with the [`dimmetadata!`](@ref), +[`deletemetadata!`](@ref), and [`emptymetadata!`](@ref) functions is supported. +""" +dimmetadatasupport(::Type, i::Int) = (read=false, write=false) + +""" + dimmetadata(x, dim::Int, key::AbstractString, [default]; style::Bool=false) + +Return metadata value associated with `x` at dimension `dim` and key `key`. +Throw an error if `x` does not support reading metadata for dimension `dim` or `x` +supports reading metadata, but does not have a mapping for dimension `dim` for `key`. + +If `style=true` return a tuple of metadata value and metadata style. Metadata +style is an additional information about the kind of metadata that is stored for +the `key`. + +$STYLE_INFO + +If `default` is passed then return it if `x` supports reading metadata and has +dimension `dim` but mapping for `key` is missing. +If `style=true` return `(default, :default)`. +""" +function dimmetadata end + +""" + dimmetadata(x, dim::Int; style::Bool=false) + +Return a dictionary of metadata corresponding to dimension `dim` of object `x`. +Throw an error if `x` does not support reading metadata corresponding to dimension `dim`. + +If `style=true` values are tuples of metadata value and metadata style. Metadata +style is an additional information about the kind of metadata that is stored for +the `key`. + +$STYLE_INFO + +The returned dictionary may be freshly allocated on each call to `metadata` and +is considered to be owned by `x` so it must not be modified. +""" +function dimmetadata(x::T, dim::Int; style::Bool=false) where {T} + if !dimmetadatasupport(T, dim).read + throw(ArgumentError("Objects of type $T do not support reading dimension metadata")) + end + return Dict(key => dimmetadata(x, dim, key, style=style) for key in dimmetadatakeys(x, dim)) +end + +""" + dimmetadatakeys(x, dim::Int) + +Return an iterator of keys for corresponding to metadata for dimension `dim` of `x`. +If `x` does not support dimension metadata return `()`. +""" +function dimmetadatakeys end + +""" + dimmetadata!(x, dim::Int, key::AbstractString, value; style::Symbol=:default) + +Set the metadata value and style associated with `x` at dimension `dim` for key `key` to `value` +and `style`, respectively. (`:default` by default) and return `x`. +Throw an error if `x` does not support setting metadata for dimension `dim`. + +$STYLE_INFO +""" +function dimmetadata! end + +""" + deletedimmetadata!(x, dim::Int, key::AbstractString) + +Delete metadata for corresponding to dimension `dim` and key `key` of `x` and return `x` +(if metadata for `key` is not present do not perform any action). +Throw an error if `x` does not support metadata deletion for dimension `dim`. +""" +function deletedimmetadata! end + +""" + emptydimmetadata!(x, dim::Int) + +Delete all metadata for `x` corresponding to dimension `dim` and return `x`. +Throw an error if `x` does not support metadata deletion for dimension `dim`. +""" +function emptydimmetadata! end + """ rownumber(row) diff --git a/test/runtests.jl b/test/runtests.jl index d70d1e5..0a5532e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -17,12 +17,22 @@ DataAPI.levels(x::TestArray) = reverse(DataAPI.levels(x.x)) struct TestMeta table::Dict{String, Any} col::Dict{Symbol, Dict{String, Any}} + dims::Tuple{Dict{String, Any}, Dict{String, Any}} - TestMeta() = new(Dict{String, Any}(), Dict{Symbol, Dict{String, Any}}()) + function TestMeta() + new(Dict{String, Any}(), Dict{Symbol, Dict{String, Any}}(), (Dict{String, Any}(), Dict{String, Any}())) + end end DataAPI.metadatasupport(::Type{TestMeta}) = (read=true, write=true) DataAPI.colmetadatasupport(::Type{TestMeta}) = (read=true, write=true) +function DataAPI.dimmetadatasupport(::Type{TestMeta}, dim::Int) + if dim === 1 || dim === 2 + (read=true, write=true) + else + (read=false, write=false) + end +end function DataAPI.metadata(x::TestMeta, key::AbstractString; style::Bool=false) return style ? x.table[key] : x.table[key][1] @@ -93,6 +103,38 @@ end DataAPI.emptycolmetadata!(x::TestMeta) = empty!(x.col) +function DataAPI.dimmetadata(x::TestMeta, dim::Int, key::AbstractString; style::Bool=false) + return style ? x.dims[dim][key] : x.dims[dim][key][1] +end + +function DataAPI.dimmetadata(x::TestMeta, dim::Int, key::AbstractString, default; style::Bool=false) + haskey(x.dims[dim], key) && return DataAPI.metadata(x, dim, key, style=style) + return style ? (default, :default) : default +end + +function DataAPI.dimmetadatakeys(x::TestMeta, dim::Int) + if DataAPI.dimmetadatasupport(TestMeta, dim).read + return keys(x.dims[dim]) + else + return () + end +end + +function DataAPI.dimmetadata!(x::TestMeta, dim::Int, key::AbstractString, value; style::Symbol=:default) + x.dims[dim][key] = (value, style) + return x +end + +function DataAPI.deletedimmetadata!(x::TestMeta, dim::Int, key::AbstractString) + delete!(x.dims[dim], key) + return x +end +function DataAPI.emptydimmetadata!(x::TestMeta, dim::Int) + empty!(x.dims[dim]) + return x +end + + # An example implementation of a table (without the Tables.jl interface) # for testing DataAPI.rownumber struct TestTable{T} @@ -301,12 +343,25 @@ end @test_throws MethodError DataAPI.colmetadatakeys(1, 1) @test_throws MethodError DataAPI.colmetadatakeys(1) + dim = 1 + @test_throws MethodError DataAPI.dimmetadata!(1, dim, "a", 10, style=:default) + @test_throws MethodError DataAPI.deletedimmetadata!(1, dim, "a") + @test_throws MethodError DataAPI.emptydimmetadata!(1, dim) + @test_throws MethodError DataAPI.dimmetadata(1, dim, "a") + @test_throws ArgumentError DataAPI.dimmetadata(1, dim) + @test_throws MethodError DataAPI.dimmetadata(1, dim, "a", style=true) + @test_throws ArgumentError DataAPI.dimmetadata(1, dim, style=true) + @test_throws MethodError DataAPI.dimmetadatakeys(1, dim) + @test DataAPI.metadatasupport(Int) == (read=false, write=false) @test DataAPI.colmetadatasupport(Int) == (read=false, write=false) + @test DataAPI.dimmetadatasupport(Int, 1) == (read=false, write=false) tm = TestMeta() @test DataAPI.metadatasupport(TestMeta) == (read=true, write=true) @test DataAPI.colmetadatasupport(TestMeta) == (read=true, write=true) + @test DataAPI.dimmetadatasupport(TestMeta, 1) == (read=true, write=true) + @test DataAPI.dimmetadatasupport(TestMeta, 0) == (read=false, write=false) @test isempty(DataAPI.metadatakeys(tm)) @test DataAPI.metadata(tm) == Dict() @@ -353,6 +408,26 @@ end @test DataAPI.colmetadata!(tm, :col, "a", "100", style=:note) == tm DataAPI.emptycolmetadata!(tm) @test isempty(DataAPI.colmetadatakeys(tm)) + + dim = 1 + @test isempty(DataAPI.dimmetadatakeys(tm, dim)) + @test DataAPI.dimmetadata(tm, dim) == Dict() + @test DataAPI.dimmetadata(tm, dim, style=true) == Dict() + @test DataAPI.dimmetadata!(tm, dim, "a", "100", style=:note) == tm + @test collect(DataAPI.dimmetadatakeys(tm, dim)) == ["a"] + @test_throws KeyError DataAPI.dimmetadata(tm, dim, "b") + @test DataAPI.dimmetadata(tm, dim, "b", 123) == 123 + @test_throws KeyError DataAPI.dimmetadata(tm, dim, "b", style=true) + @test DataAPI.dimmetadata(tm, dim, "b", 123, style=true) == (123, :default) + @test DataAPI.dimmetadata(tm, dim, "a") == "100" + @test DataAPI.dimmetadata(tm, dim) == Dict("a" => "100") + @test DataAPI.dimmetadata(tm, dim, "a", style=true) == ("100", :note) + @test DataAPI.dimmetadata(tm, dim, style=true) == Dict("a" => ("100", :note)) + DataAPI.deletedimmetadata!(tm, dim, "a") + @test isempty(DataAPI.dimmetadatakeys(tm, dim)) + @test DataAPI.dimmetadata!(tm, dim, "a", "100", style=:note) == tm + DataAPI.emptydimmetadata!(tm, dim) + @test isempty(DataAPI.dimmetadatakeys(tm, dim)) end @testset "rownumber" begin From 47daf4c02ea2810e74a9f449b621fa62c29d5c1f Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Tue, 11 Jul 2023 08:27:48 -0400 Subject: [PATCH 02/26] Update test/runtests.jl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bogumił Kamiński --- test/runtests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index 0a5532e..ea912a0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -27,7 +27,7 @@ end DataAPI.metadatasupport(::Type{TestMeta}) = (read=true, write=true) DataAPI.colmetadatasupport(::Type{TestMeta}) = (read=true, write=true) function DataAPI.dimmetadatasupport(::Type{TestMeta}, dim::Int) - if dim === 1 || dim === 2 + if dim == 1 || dim == 2 (read=true, write=true) else (read=false, write=false) From e1b08c588be65333279d8102bf78316a89d10317 Mon Sep 17 00:00:00 2001 From: "Zachary P. Christensen" Date: Wed, 12 Jul 2023 08:22:15 -0400 Subject: [PATCH 03/26] Version bump and delete unnecessary line --- Project.toml | 2 +- test/runtests.jl | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index 18e0204..d67a8df 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "DataAPI" uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" authors = ["quinnj "] -version = "1.15.0" +version = "1.16.0" [compat] julia = "1" diff --git a/test/runtests.jl b/test/runtests.jl index ea912a0..9fdc53f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -409,7 +409,6 @@ end DataAPI.emptycolmetadata!(tm) @test isempty(DataAPI.colmetadatakeys(tm)) - dim = 1 @test isempty(DataAPI.dimmetadatakeys(tm, dim)) @test DataAPI.dimmetadata(tm, dim) == Dict() @test DataAPI.dimmetadata(tm, dim, style=true) == Dict() From 19287e03e01789932abe558dfeebeeda27084d38 Mon Sep 17 00:00:00 2001 From: "Zachary P. Christensen" Date: Sun, 6 Aug 2023 21:13:16 -0400 Subject: [PATCH 04/26] Make docs more consistent with colmetadata --- src/DataAPI.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index fd4149f..f55eb04 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -532,7 +532,7 @@ dimmetadatasupport(::Type, i::Int) = (read=false, write=false) """ dimmetadata(x, dim::Int, key::AbstractString, [default]; style::Bool=false) -Return metadata value associated with `x` at dimension `dim` and key `key`. +Return metadata value associated with `x` for dimension `dim` and key `key`. Throw an error if `x` does not support reading metadata for dimension `dim` or `x` supports reading metadata, but does not have a mapping for dimension `dim` for `key`. @@ -581,8 +581,8 @@ function dimmetadatakeys end """ dimmetadata!(x, dim::Int, key::AbstractString, value; style::Symbol=:default) -Set the metadata value and style associated with `x` at dimension `dim` for key `key` to `value` -and `style`, respectively. (`:default` by default) and return `x`. +Set metadata for `x` for dimension `dim` for key `key` to have value `value` +and style `style` (`:default` by default) and return `x`. Throw an error if `x` does not support setting metadata for dimension `dim`. $STYLE_INFO From 10ca2f0ce25546ad899af861a5c1c2c6c86b86c9 Mon Sep 17 00:00:00 2001 From: "Zachary P. Christensen" Date: Sun, 13 Aug 2023 17:08:35 -0400 Subject: [PATCH 05/26] remove `dim` --- test/runtests.jl | 53 ++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 9fdc53f..609eca0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -343,15 +343,14 @@ end @test_throws MethodError DataAPI.colmetadatakeys(1, 1) @test_throws MethodError DataAPI.colmetadatakeys(1) - dim = 1 - @test_throws MethodError DataAPI.dimmetadata!(1, dim, "a", 10, style=:default) - @test_throws MethodError DataAPI.deletedimmetadata!(1, dim, "a") - @test_throws MethodError DataAPI.emptydimmetadata!(1, dim) - @test_throws MethodError DataAPI.dimmetadata(1, dim, "a") - @test_throws ArgumentError DataAPI.dimmetadata(1, dim) - @test_throws MethodError DataAPI.dimmetadata(1, dim, "a", style=true) - @test_throws ArgumentError DataAPI.dimmetadata(1, dim, style=true) - @test_throws MethodError DataAPI.dimmetadatakeys(1, dim) + @test_throws MethodError DataAPI.dimmetadata!(1, 1, "a", 10, style=:default) + @test_throws MethodError DataAPI.deletedimmetadata!(1, 1, "a") + @test_throws MethodError DataAPI.emptydimmetadata!(1, 1) + @test_throws MethodError DataAPI.dimmetadata(1, 1, "a") + @test_throws ArgumentError DataAPI.dimmetadata(1, 1) + @test_throws MethodError DataAPI.dimmetadata(1, 1, "a", style=true) + @test_throws ArgumentError DataAPI.dimmetadata(1, 1, style=true) + @test_throws MethodError DataAPI.dimmetadatakeys(1, 1) @test DataAPI.metadatasupport(Int) == (read=false, write=false) @test DataAPI.colmetadatasupport(Int) == (read=false, write=false) @@ -409,24 +408,24 @@ end DataAPI.emptycolmetadata!(tm) @test isempty(DataAPI.colmetadatakeys(tm)) - @test isempty(DataAPI.dimmetadatakeys(tm, dim)) - @test DataAPI.dimmetadata(tm, dim) == Dict() - @test DataAPI.dimmetadata(tm, dim, style=true) == Dict() - @test DataAPI.dimmetadata!(tm, dim, "a", "100", style=:note) == tm - @test collect(DataAPI.dimmetadatakeys(tm, dim)) == ["a"] - @test_throws KeyError DataAPI.dimmetadata(tm, dim, "b") - @test DataAPI.dimmetadata(tm, dim, "b", 123) == 123 - @test_throws KeyError DataAPI.dimmetadata(tm, dim, "b", style=true) - @test DataAPI.dimmetadata(tm, dim, "b", 123, style=true) == (123, :default) - @test DataAPI.dimmetadata(tm, dim, "a") == "100" - @test DataAPI.dimmetadata(tm, dim) == Dict("a" => "100") - @test DataAPI.dimmetadata(tm, dim, "a", style=true) == ("100", :note) - @test DataAPI.dimmetadata(tm, dim, style=true) == Dict("a" => ("100", :note)) - DataAPI.deletedimmetadata!(tm, dim, "a") - @test isempty(DataAPI.dimmetadatakeys(tm, dim)) - @test DataAPI.dimmetadata!(tm, dim, "a", "100", style=:note) == tm - DataAPI.emptydimmetadata!(tm, dim) - @test isempty(DataAPI.dimmetadatakeys(tm, dim)) + @test isempty(DataAPI.dimmetadatakeys(tm, 1)) + @test DataAPI.dimmetadata(tm, 1) == Dict() + @test DataAPI.dimmetadata(tm, 1, style=true) == Dict() + @test DataAPI.dimmetadata!(tm, 1, "a", "100", style=:note) == tm + @test collect(DataAPI.dimmetadatakeys(tm, 1)) == ["a"] + @test_throws KeyError DataAPI.dimmetadata(tm, 1, "b") + @test DataAPI.dimmetadata(tm, 1, "b", 123) == 123 + @test_throws KeyError DataAPI.dimmetadata(tm, 1, "b", style=true) + @test DataAPI.dimmetadata(tm, 1, "b", 123, style=true) == (123, :default) + @test DataAPI.dimmetadata(tm, 1, "a") == "100" + @test DataAPI.dimmetadata(tm, 1) == Dict("a" => "100") + @test DataAPI.dimmetadata(tm, 1, "a", style=true) == ("100", :note) + @test DataAPI.dimmetadata(tm, 1, style=true) == Dict("a" => ("100", :note)) + DataAPI.deletedimmetadata!(tm, 1, "a") + @test isempty(DataAPI.dimmetadatakeys(tm, 1)) + @test DataAPI.dimmetadata!(tm, 1, "a", "100", style=:note) == tm + DataAPI.emptydimmetadata!(tm, 1) + @test isempty(DataAPI.dimmetadatakeys(tm, 1)) end @testset "rownumber" begin From bbe4fc7dc31101266931518439a34cb2e1b3e39c Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Mon, 14 Aug 2023 21:04:17 -0400 Subject: [PATCH 06/26] Update src/DataAPI.jl Co-authored-by: Milan Bouchet-Valat --- src/DataAPI.jl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index f55eb04..374adbd 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -571,9 +571,14 @@ function dimmetadata(x::T, dim::Int; style::Bool=false) where {T} end """ - dimmetadatakeys(x, dim::Int) + dimmetadatakeys(x, [dim::Int]) -Return an iterator of keys for corresponding to metadata for dimension `dim` of `x`. +If `dim` is passed return an iterator of metadata keys for which +`metadata(x, dim, key)` returns a metadata value. Throw an error if `x` does not +support reading column metadata or if `dim` is not a dimension of `x`. + +If `dim` is not passed return an iterator of `dim => colmetadatakeys(x, dim)` +pairs for all dimensions that have metadata. If `x` does not support dimension metadata return `()`. """ function dimmetadatakeys end From ffbb5824a16046f7e76d73c198e2a9e28010d536 Mon Sep 17 00:00:00 2001 From: "Zachary P. Christensen" Date: Tue, 15 Aug 2023 01:26:20 -0400 Subject: [PATCH 07/26] fix typos --- src/DataAPI.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index 374adbd..cf68004 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -472,7 +472,7 @@ end colmetadatakeys(x, [col]) If `col` is passed return an iterator of metadata keys for which -`metadata(x, col, key)` returns a metadata value. Throw an error if `x` does not +`colmetadata(x, col, key)` returns a metadata value. Throw an error if `x` does not support reading column metadata or if `col` is not a column of `x`. `col` must have a type that is supported by table `x` for column indexing. @@ -574,10 +574,10 @@ end dimmetadatakeys(x, [dim::Int]) If `dim` is passed return an iterator of metadata keys for which -`metadata(x, dim, key)` returns a metadata value. Throw an error if `x` does not -support reading column metadata or if `dim` is not a dimension of `x`. +`dimmetadata(x, dim, key)` returns a metadata value. Throw an error if `x` does not +support reading dimension metadata or if `dim` is not a dimension of `x`. -If `dim` is not passed return an iterator of `dim => colmetadatakeys(x, dim)` +If `dim` is not passed return an iterator of `dim => dimmetadatakeys(x, dim)` pairs for all dimensions that have metadata. If `x` does not support dimension metadata return `()`. """ From 3a0466f971b56892e2865c860d68537b85efba1a Mon Sep 17 00:00:00 2001 From: "Zachary P. Christensen" Date: Tue, 15 Aug 2023 02:02:04 -0400 Subject: [PATCH 08/26] Support `dimmetadata` and `dimmetadatakeys` without `dim` arg --- src/DataAPI.jl | 17 ++++++++++++++--- test/runtests.jl | 5 ++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index cf68004..31c01d7 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -551,7 +551,9 @@ function dimmetadata end """ dimmetadata(x, dim::Int; style::Bool=false) -Return a dictionary of metadata corresponding to dimension `dim` of object `x`. +Return a dictionary of metadata corresponding to dimension `dim` of object `x`. If `dim` + is not passed return a collection mapping each dimension to its metadata so that +`collection[dim][key] == dimmetadata(x, dim, key)`. Throw an error if `x` does not support reading metadata corresponding to dimension `dim`. If `style=true` values are tuples of metadata value and metadata style. Metadata @@ -560,7 +562,7 @@ the `key`. $STYLE_INFO -The returned dictionary may be freshly allocated on each call to `metadata` and +The returned dictionary may be freshly allocated on each call to `dimmetadata` and is considered to be owned by `x` so it must not be modified. """ function dimmetadata(x::T, dim::Int; style::Bool=false) where {T} @@ -569,6 +571,9 @@ function dimmetadata(x::T, dim::Int; style::Bool=false) where {T} end return Dict(key => dimmetadata(x, dim, key, style=style) for key in dimmetadatakeys(x, dim)) end +function dimmetadata(x::T; style::Bool=false) where {T} + Tuple(dimmetadata(x, dim; style=style) for dim in 1:ndims(x)) +end """ dimmetadatakeys(x, [dim::Int]) @@ -581,7 +586,13 @@ If `dim` is not passed return an iterator of `dim => dimmetadatakeys(x, dim)` pairs for all dimensions that have metadata. If `x` does not support dimension metadata return `()`. """ -function dimmetadatakeys end +function dimmetadatakeys(x, dim::Int) + dimmetadatasupport(typeof(x), dim).read || return () + throw(MethodError(dimmetadatakeys, (x, dim))) +end +function dimmetadatakeys(x) + Dict(dim => dimmetadatakeys(x, dim) for dim in 1:ndims(x)) +end """ dimmetadata!(x, dim::Int, key::AbstractString, value; style::Symbol=:default) diff --git a/test/runtests.jl b/test/runtests.jl index 609eca0..b95fc09 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -23,6 +23,7 @@ struct TestMeta new(Dict{String, Any}(), Dict{Symbol, Dict{String, Any}}(), (Dict{String, Any}(), Dict{String, Any}())) end end +Base.ndims(::TestMeta) = 2 DataAPI.metadatasupport(::Type{TestMeta}) = (read=true, write=true) DataAPI.colmetadatasupport(::Type{TestMeta}) = (read=true, write=true) @@ -350,7 +351,6 @@ end @test_throws ArgumentError DataAPI.dimmetadata(1, 1) @test_throws MethodError DataAPI.dimmetadata(1, 1, "a", style=true) @test_throws ArgumentError DataAPI.dimmetadata(1, 1, style=true) - @test_throws MethodError DataAPI.dimmetadatakeys(1, 1) @test DataAPI.metadatasupport(Int) == (read=false, write=false) @test DataAPI.colmetadatasupport(Int) == (read=false, write=false) @@ -409,7 +409,9 @@ end @test isempty(DataAPI.colmetadatakeys(tm)) @test isempty(DataAPI.dimmetadatakeys(tm, 1)) + @test isempty(DataAPI.dimmetadatakeys(tm)[1]) @test DataAPI.dimmetadata(tm, 1) == Dict() + @test DataAPI.dimmetadata(tm) == (Dict(), Dict()) @test DataAPI.dimmetadata(tm, 1, style=true) == Dict() @test DataAPI.dimmetadata!(tm, 1, "a", "100", style=:note) == tm @test collect(DataAPI.dimmetadatakeys(tm, 1)) == ["a"] @@ -419,6 +421,7 @@ end @test DataAPI.dimmetadata(tm, 1, "b", 123, style=true) == (123, :default) @test DataAPI.dimmetadata(tm, 1, "a") == "100" @test DataAPI.dimmetadata(tm, 1) == Dict("a" => "100") + @test DataAPI.dimmetadata(tm)[1] == Dict("a" => "100") @test DataAPI.dimmetadata(tm, 1, "a", style=true) == ("100", :note) @test DataAPI.dimmetadata(tm, 1, style=true) == Dict("a" => ("100", :note)) DataAPI.deletedimmetadata!(tm, 1, "a") From 1a418e39da6fa2291b07691044c3a5c87faca0b0 Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Wed, 16 Aug 2023 10:25:17 -0400 Subject: [PATCH 09/26] Update src/DataAPI.jl Co-authored-by: Milan Bouchet-Valat --- src/DataAPI.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index 31c01d7..9a4cdcb 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -562,7 +562,7 @@ the `key`. $STYLE_INFO -The returned dictionary may be freshly allocated on each call to `dimmetadata` and +The returned object may be freshly allocated on each call to `dimmetadata` and is considered to be owned by `x` so it must not be modified. """ function dimmetadata(x::T, dim::Int; style::Bool=false) where {T} From 115962f727612238dcab4d783fe598de9d0b9cee Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Wed, 16 Aug 2023 10:28:19 -0400 Subject: [PATCH 10/26] Update src/DataAPI.jl Co-authored-by: Milan Bouchet-Valat --- src/DataAPI.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index 9a4cdcb..af8ce95 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -608,7 +608,7 @@ function dimmetadata! end """ deletedimmetadata!(x, dim::Int, key::AbstractString) -Delete metadata for corresponding to dimension `dim` and key `key` of `x` and return `x` +Delete metadata corresponding to dimension `dim` of `x` for key `key` and return `x` (if metadata for `key` is not present do not perform any action). Throw an error if `x` does not support metadata deletion for dimension `dim`. """ From 7cb0aefa0fc1c8d7c3b0ed063e4aad23323ab7f2 Mon Sep 17 00:00:00 2001 From: "Zachary P. Christensen" Date: Wed, 4 Oct 2023 15:30:47 -0400 Subject: [PATCH 11/26] Improve docs for metadata keys for dims and cols --- src/DataAPI.jl | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index af8ce95..9a689cf 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -480,7 +480,9 @@ Following the Tables.jl contract `Symbol` and `Int` are always allowed. If `col` is not passed return an iterator of `col => colmetadatakeys(x, col)` pairs for all columns that have metadata, where `col` are `Symbol`. -If `x` does not support column metadata return `()`. + +If `colmetadatasupport(typeof(x)).read` or `colmetadatasupport(typeof(x)).write` return `true` +this should also be defined. """ function colmetadatakeys end @@ -584,15 +586,11 @@ support reading dimension metadata or if `dim` is not a dimension of `x`. If `dim` is not passed return an iterator of `dim => dimmetadatakeys(x, dim)` pairs for all dimensions that have metadata. -If `x` does not support dimension metadata return `()`. + +If `dimmetadatasupport(typeof(x)).read` or `dimmetadatasupport(typeof(x)).write` return `true` +this should also be defined. """ -function dimmetadatakeys(x, dim::Int) - dimmetadatasupport(typeof(x), dim).read || return () - throw(MethodError(dimmetadatakeys, (x, dim))) -end -function dimmetadatakeys(x) - Dict(dim => dimmetadatakeys(x, dim) for dim in 1:ndims(x)) -end +function dimmetadatakeys end """ dimmetadata!(x, dim::Int, key::AbstractString, value; style::Symbol=:default) From 0d5bb5cdcc0e4c0132deefbd09e5c3d3f2deb581 Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Sun, 24 Dec 2023 14:27:57 -0500 Subject: [PATCH 12/26] Update src/DataAPI.jl Co-authored-by: Milan Bouchet-Valat --- src/DataAPI.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index 9a689cf..137c287 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -573,7 +573,7 @@ function dimmetadata(x::T, dim::Int; style::Bool=false) where {T} end return Dict(key => dimmetadata(x, dim, key, style=style) for key in dimmetadatakeys(x, dim)) end -function dimmetadata(x::T; style::Bool=false) where {T} +function dimmetadata(x; style::Bool=false) Tuple(dimmetadata(x, dim; style=style) for dim in 1:ndims(x)) end From 4a11c371349a3c2aaef0eceef0720fb426ad3319 Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Sun, 24 Dec 2023 14:48:07 -0500 Subject: [PATCH 13/26] Update src/DataAPI.jl Co-authored-by: Milan Bouchet-Valat --- src/DataAPI.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index 137c287..3ffef5b 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -551,7 +551,7 @@ If `style=true` return `(default, :default)`. function dimmetadata end """ - dimmetadata(x, dim::Int; style::Bool=false) + dimmetadata(x, [dim::Int]; style::Bool=false) Return a dictionary of metadata corresponding to dimension `dim` of object `x`. If `dim` is not passed return a collection mapping each dimension to its metadata so that From 8225a7ec4e0a1805b6728a7bdad6615d49dc5d2f Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Sun, 24 Dec 2023 14:48:44 -0500 Subject: [PATCH 14/26] Update test/runtests.jl Co-authored-by: Milan Bouchet-Valat --- test/runtests.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/runtests.jl b/test/runtests.jl index b95fc09..3f19e6b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -130,6 +130,7 @@ function DataAPI.deletedimmetadata!(x::TestMeta, dim::Int, key::AbstractString) delete!(x.dims[dim], key) return x end + function DataAPI.emptydimmetadata!(x::TestMeta, dim::Int) empty!(x.dims[dim]) return x From 2ae276851772d69a1fba378282b02cac334095e7 Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Sun, 24 Dec 2023 14:49:10 -0500 Subject: [PATCH 15/26] Update src/DataAPI.jl Co-authored-by: Milan Bouchet-Valat --- src/DataAPI.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index 3ffef5b..22252ae 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -480,6 +480,7 @@ Following the Tables.jl contract `Symbol` and `Int` are always allowed. If `col` is not passed return an iterator of `col => colmetadatakeys(x, col)` pairs for all columns that have metadata, where `col` are `Symbol`. +If `x` does not support column metadata return `()`. If `colmetadatasupport(typeof(x)).read` or `colmetadatasupport(typeof(x)).write` return `true` this should also be defined. From 57e4f8c5afe81cbe63b623cd881ce5efee1f4873 Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Sun, 24 Dec 2023 14:51:19 -0500 Subject: [PATCH 16/26] Update src/DataAPI.jl Co-authored-by: Milan Bouchet-Valat --- src/DataAPI.jl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index 22252ae..83104e0 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -554,9 +554,14 @@ function dimmetadata end """ dimmetadata(x, [dim::Int]; style::Bool=false) -Return a dictionary of metadata corresponding to dimension `dim` of object `x`. If `dim` - is not passed return a collection mapping each dimension to its metadata so that -`collection[dim][key] == dimmetadata(x, dim, key)`. +If `dim` is not passed, return a dictionary mapping dimensions that have +associated metadata to dictionaries mapping all metadata keys to metadata +values associated with object `x` for a given dimension, so that +`colmetadata(x)[dim][key] == dimmetadata(x, dim, key)`. + +If `dim` is passed return a dictionary mapping all column metadata keys +to metadata values associated with dimension `dim` of object `x`, so that +`colmetadata(x, dim)[key] == dimmetadata(x, dim, key)`. Throw an error if `x` does not support reading metadata corresponding to dimension `dim`. If `style=true` values are tuples of metadata value and metadata style. Metadata From e68ece24a8bb0b81b9d0f0b3fb15aba9402c9452 Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Sun, 24 Dec 2023 14:52:04 -0500 Subject: [PATCH 17/26] Update src/DataAPI.jl Co-authored-by: Milan Bouchet-Valat --- src/DataAPI.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index 83104e0..845c6a1 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -562,7 +562,8 @@ values associated with object `x` for a given dimension, so that If `dim` is passed return a dictionary mapping all column metadata keys to metadata values associated with dimension `dim` of object `x`, so that `colmetadata(x, dim)[key] == dimmetadata(x, dim, key)`. -Throw an error if `x` does not support reading metadata corresponding to dimension `dim`. +Throw an error if `x` does not support reading metadata for dimension `dim` +or `dim` is not dimension of `x`. If `style=true` values are tuples of metadata value and metadata style. Metadata style is an additional information about the kind of metadata that is stored for From c35f7a124e6b7fe85efcd9d1751ecbd84f849bab Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Sun, 24 Dec 2023 14:56:41 -0500 Subject: [PATCH 18/26] Update src/DataAPI.jl Co-authored-by: Milan Bouchet-Valat --- src/DataAPI.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index 845c6a1..3be3082 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -482,8 +482,8 @@ If `col` is not passed return an iterator of `col => colmetadatakeys(x, col)` pairs for all columns that have metadata, where `col` are `Symbol`. If `x` does not support column metadata return `()`. -If `colmetadatasupport(typeof(x)).read` or `colmetadatasupport(typeof(x)).write` return `true` -this should also be defined. +This method must be defined if `dimmetadatasupport(typeof(x)).read` or +`dimmetadatasupport(typeof(x)).write` return `true`. """ function colmetadatakeys end From a3ecbcd23684f86da8733ce3588e1022780f9975 Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Sun, 24 Dec 2023 14:57:52 -0500 Subject: [PATCH 19/26] Update src/DataAPI.jl Co-authored-by: Milan Bouchet-Valat --- src/DataAPI.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index 3be3082..e4e7d6e 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -594,8 +594,8 @@ support reading dimension metadata or if `dim` is not a dimension of `x`. If `dim` is not passed return an iterator of `dim => dimmetadatakeys(x, dim)` pairs for all dimensions that have metadata. -If `dimmetadatasupport(typeof(x)).read` or `dimmetadatasupport(typeof(x)).write` return `true` -this should also be defined. +This method must be defined if `dimmetadatasupport(typeof(x)).read` or +`dimmetadatasupport(typeof(x)).write` return `true`. """ function dimmetadatakeys end From b519d2610539cdf7e333058aa775a4962329ca82 Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Sun, 24 Dec 2023 14:58:32 -0500 Subject: [PATCH 20/26] Update src/DataAPI.jl Co-authored-by: Milan Bouchet-Valat --- src/DataAPI.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index e4e7d6e..498f61b 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -535,7 +535,7 @@ dimmetadatasupport(::Type, i::Int) = (read=false, write=false) """ dimmetadata(x, dim::Int, key::AbstractString, [default]; style::Bool=false) -Return metadata value associated with `x` for dimension `dim` and key `key`. +Return metadata value associated with object `x` for dimension `dim` and key `key`. Throw an error if `x` does not support reading metadata for dimension `dim` or `x` supports reading metadata, but does not have a mapping for dimension `dim` for `key`. From ab256ec6c94b85a88febaa934ab68ca72f70981e Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Sun, 24 Dec 2023 14:58:56 -0500 Subject: [PATCH 21/26] Update src/DataAPI.jl Co-authored-by: Milan Bouchet-Valat --- src/DataAPI.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index 498f61b..73860e9 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -613,7 +613,7 @@ function dimmetadata! end """ deletedimmetadata!(x, dim::Int, key::AbstractString) -Delete metadata corresponding to dimension `dim` of `x` for key `key` and return `x` +Delete metadata for object `x` for dimension `dim` for key `key` and return `x` (if metadata for `key` is not present do not perform any action). Throw an error if `x` does not support metadata deletion for dimension `dim`. """ From 838047ac994ccac0c00fc58e551ec9e51437bbff Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Sun, 24 Dec 2023 14:59:40 -0500 Subject: [PATCH 22/26] Update src/DataAPI.jl Co-authored-by: Milan Bouchet-Valat --- src/DataAPI.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index 73860e9..e8bd9dc 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -622,7 +622,7 @@ function deletedimmetadata! end """ emptydimmetadata!(x, dim::Int) -Delete all metadata for `x` corresponding to dimension `dim` and return `x`. +Delete all metadata for object `x` for to dimension `dim` and return `x`. Throw an error if `x` does not support metadata deletion for dimension `dim`. """ function emptydimmetadata! end From c0ae55796410fa4235c737fb8c72132ae8f2e0be Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Sun, 24 Dec 2023 14:59:56 -0500 Subject: [PATCH 23/26] Update src/DataAPI.jl Co-authored-by: Milan Bouchet-Valat --- src/DataAPI.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index e8bd9dc..badd79e 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -602,7 +602,7 @@ function dimmetadatakeys end """ dimmetadata!(x, dim::Int, key::AbstractString, value; style::Symbol=:default) -Set metadata for `x` for dimension `dim` for key `key` to have value `value` +Set metadata for object `x` for dimension `dim` for key `key` to have value `value` and style `style` (`:default` by default) and return `x`. Throw an error if `x` does not support setting metadata for dimension `dim`. From 2e343f4b35155bd009db7ccdb390805b65ee20a6 Mon Sep 17 00:00:00 2001 From: Zachary P Christensen Date: Sun, 24 Dec 2023 15:01:00 -0500 Subject: [PATCH 24/26] Update src/DataAPI.jl Co-authored-by: Milan Bouchet-Valat --- src/DataAPI.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index badd79e..6c31e8e 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -623,6 +623,7 @@ function deletedimmetadata! end emptydimmetadata!(x, dim::Int) Delete all metadata for object `x` for to dimension `dim` and return `x`. +If `dim` is not passed delete all dimension level metadata for table `x`. Throw an error if `x` does not support metadata deletion for dimension `dim`. """ function emptydimmetadata! end From b01d2c24de0ef6fea1ebd9d244f9be4530728e6e Mon Sep 17 00:00:00 2001 From: "Zachary P. Christensen" Date: Sun, 24 Dec 2023 15:04:09 -0500 Subject: [PATCH 25/26] Add doc to sync metadatakeys and metadatasupport --- src/DataAPI.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index 6c31e8e..f54e55e 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -381,6 +381,9 @@ end Return an iterator of metadata keys for which `metadata(x, key)` returns a metadata value. Throw an error if `x` does not support reading metadata. + +If `metadatasupport(typeof(x)).read` or `metadatasupport(typeof(x)).write` return `true` +this should also be defined. """ function metadatakeys end From 6a0af432f86e14cec64e1a4a73428ef2e4e7e3f2 Mon Sep 17 00:00:00 2001 From: "Zachary P. Christensen" Date: Sun, 24 Dec 2023 15:58:36 -0500 Subject: [PATCH 26/26] Move `colmetadatasupport` above colmeta functions --- src/DataAPI.jl | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/DataAPI.jl b/src/DataAPI.jl index f54e55e..72fb404 100644 --- a/src/DataAPI.jl +++ b/src/DataAPI.jl @@ -322,20 +322,6 @@ The `write` field indicates whether modifying metadata with the [`metadata!`](@r """ metadatasupport(::Type) = (read=false, write=false) -""" - colmetadatasupport(T::Type) - -Return a `NamedTuple{(:read, :write), Tuple{Bool, Bool}}` indicating whether -values of type `T` support column metadata. - -The `read` field indicates whether reading metadata with the [`colmetadata`](@ref) -and [`colmetadatakeys`](@ref) functions is supported. - -The `write` field indicates whether modifying metadata with the [`colmetadata!`](@ref), -[`deletecolmetadata!`](@ref), and [`emptycolmetadata!`](@ref) functions is supported. -""" -colmetadatasupport(::Type) = (read=false, write=false) - """ metadata(x, key::AbstractString, [default]; style::Bool=false) @@ -415,6 +401,20 @@ Throw an error if `x` does not support metadata deletion. """ function emptymetadata! end +""" + colmetadatasupport(T::Type) + +Return a `NamedTuple{(:read, :write), Tuple{Bool, Bool}}` indicating whether +values of type `T` support column metadata. + +The `read` field indicates whether reading metadata with the [`colmetadata`](@ref) +and [`colmetadatakeys`](@ref) functions is supported. + +The `write` field indicates whether modifying metadata with the [`colmetadata!`](@ref), +[`deletecolmetadata!`](@ref), and [`emptycolmetadata!`](@ref) functions is supported. +""" +colmetadatasupport(::Type) = (read=false, write=false) + """ colmetadata(x, col, key::AbstractString, [default]; style::Bool=false) @@ -485,8 +485,8 @@ If `col` is not passed return an iterator of `col => colmetadatakeys(x, col)` pairs for all columns that have metadata, where `col` are `Symbol`. If `x` does not support column metadata return `()`. -This method must be defined if `dimmetadatasupport(typeof(x)).read` or -`dimmetadatasupport(typeof(x)).write` return `true`. +This method must be defined if `colmetadatasupport(typeof(x)).read` or +`colmetadatasupport(typeof(x)).write` return `true`. """ function colmetadatakeys end