Skip to content

Commit

Permalink
Common way of setting metadata interface.
Browse files Browse the repository at this point in the history
  • Loading branch information
Tokazama committed Aug 1, 2020
1 parent 5324679 commit e5d5d9b
Show file tree
Hide file tree
Showing 12 changed files with 119 additions and 27 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "AxisIndices"
uuid = "f52c9ee2-1b1c-4fd8-8546-6350938c7f11"
authors = ["Tokazama <zchristensen7@gmail.com>"]
version = "0.6.2"
version = "0.6.3"

[deps]
ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
Expand Down
3 changes: 2 additions & 1 deletion docs/src/metadata.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


```@docs
Metadata.MetadataArray
Metadata.MetaAxis
Metadata.MetaAxisArray
Metadata.MetaCartesianAxes
Expand All @@ -19,4 +20,4 @@ Metadata.metadata
Metadata.metaproperty
Metadata.metaproperty!
Metadata.metadata_type
```
```
14 changes: 14 additions & 0 deletions src/AxisIndices.jl
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,18 @@ PrettyArrays.@assign_show NamedMetaCartesianAxes

PrettyArrays.@assign_show NamedMetaLinearAxes

###
### Overload property methods for metadata
###

Metadata.@metadata_properties MetaAxis

Metadata.@metadata_properties MetadataArray

Metadata.@metadata_properties NamedMetaLinearAxes

Metadata.@metadata_properties NamedMetaCartesianAxes

Metadata.@metadata_properties NamedMetaAxisArray

end
2 changes: 0 additions & 2 deletions src/Interface/Interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ using StaticRanges
using StaticRanges: OneToUnion
using StaticRanges: resize_last

import MetadataArrays: MetadataArray

using MappedArrays: ReadonlyMultiMappedArray, MultiMappedArray, ReadonlyMappedArray
using EllipsisNotation: Ellipsis
using Base: @propagate_inbounds, OneTo, Fix2, tail, front
Expand Down
4 changes: 0 additions & 4 deletions src/Metadata/MetaAxis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,6 @@ function Interface.unsafe_reconstruct(axis::MetaAxis, ks)
return MetaAxis(Interface.unsafe_reconstruct(parent(axis), ks), metadata(axis))
end

Base.getproperty(axis::MetaAxis, k::Symbol) = metaproperty(axis, k)

Base.setproperty!(axis::MetaAxis, k::Symbol, val) = metaproperty!(axis, k, val)

"""
meta(x)
Expand Down
4 changes: 0 additions & 4 deletions src/Metadata/MetaAxisArray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,4 @@ function MetaAxisArray{T,N}(init::ArrayInitializer, axs::Tuple; metadata=nothing
return MetaAxisArray(AxisArray{T,N}(init, axs); metadata=metadata, kwargs...)
end

Base.getproperty(A::MetaAxisArray, k::Symbol) = metaproperty(A, k)

Base.setproperty!(A::MetaAxisArray, k::Symbol, val) = metaproperty!(A, k, val)

Base.parent(A::MetaAxisArray) = getfield(A, :parent)
13 changes: 12 additions & 1 deletion src/Metadata/Metadata.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ using EllipsisNotation: Ellipsis
using Base: @propagate_inbounds, Fix2

export
MetadataArray,
MetaAxis,
MetaAxisArray,
MetaCartesianAxes,
Expand All @@ -41,8 +42,8 @@ export
metaproperty!,
metadata_type

import MetadataArrays: MetadataArray

include("MetadataArray.jl")
include("interface.jl")
include("MetaAxis.jl")
include("MetaCartesianAxes.jl")
Expand All @@ -52,4 +53,14 @@ include("NamedMetaAxisArray.jl")
include("NamedMetaCartesianAxes.jl")
include("NamedMetaLinearAxes.jl")

macro metadata_properties(T)
quote
@inline Base.getproperty(x::$T, k::Symbol) = Metadata.metaproperty(x, k)

@inline Base.setproperty!(x::$T, k::Symbol, val) = Metadata.metaproperty!(x, k, val)

@inline Base.propertynames(x::$T) = Metadata.metanames(x)
end
end

end
71 changes: 71 additions & 0 deletions src/Metadata/MetadataArray.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@

"""
MetadataArray(parent::AbstractArray, metadata)
Custom `AbstractArray` object to store an `AbstractArray` `parent` as well as some `metadata`.
# Examples
```jldoctest metadataarray
julia> using AxisIndices
julia> v = ["John", "John", "Jane", "Louise"];
julia> s = MetadataArray(v, Dict("John" => "Treatment", "Louise" => "Placebo", "Jane" => "Placebo"))
4-element MetadataArray{String,1,Dict{String,String},Array{String,1}}:
"John"
"John"
"Jane"
"Louise"
julia> metadata(s)
Dict{String,String} with 3 entries:
"John" => "Treatment"
"Jane" => "Placebo"
"Louise" => "Placebo"
```
"""
struct MetadataArray{T, N, M, A<:AbstractArray} <: AbstractArray{T, N}
parent::A
metadata::M
end

Base.parent(A::MetadataArray) = getfield(A, :parent)

function MetadataArray(v::AbstractArray{T, N}, m::M = ()) where {T, N, M}
return MetadataArray{T, N, M, typeof(v)}(v, m)
end

"""
MetadataVector{T, M, S<:AbstractArray}
Shorthand for `MetadataArray{T, 1, M, S}`.
"""
const MetadataVector{T, M, S<:AbstractArray} = MetadataArray{T, 1, M, S}

MetadataVector(v::AbstractVector, n = ()) = MetadataArray(v, n)

Base.size(s::MetadataArray) = Base.size(parent(s))

Base.axes(s::MetadataArray) = Base.axes(parent(s))

Base.IndexStyle(T::Type{<:MetadataArray}) = IndexStyle(parent_type(T))

@propagate_inbounds function Base.getindex(A::MetadataArray, args::Int...)
return getindex(parent(A), args...)
end

Base.@propagate_inbounds function Base.setindex!(A::MetadataArray, val, args::Int...)
return setindex!(A, val, args...)
end

ArrayInterface.parent_type(::Type{MetadataArray{T, M, N, A}}) where {T,M,N,A} = A

function Base.similar(A::MetadataArray, ::Type{S}, dims::Dims) where S
return MetadataArray(similar(parent(A), S, dims), metadata(A))
end

function Base.reshape(s::MetadataArray, d::Dims)
return MetadataArray(reshape(parent(s), d), metadata(s))
end

4 changes: 0 additions & 4 deletions src/Metadata/NamedMetaAxisArray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,6 @@ function NamedMetaAxisArray(A::AbstractArray, axs::NamedTuple{L}; metadata=nothi
return NamedMetaAxisArray{L}(A, values(axs); metadata=metadata, kwargs...)
end

Base.getproperty(A::NamedMetaAxisArray, k::Symbol) = metaproperty(A, k)

Base.setproperty!(A::NamedMetaAxisArray, k::Symbol, val) = metaproperty!(A, k, val)

for f in (:getindex, :view, :dotview)
@eval begin
@propagate_inbounds function Base.$f(A::NamedMetaAxisArray; named_inds...)
Expand Down
25 changes: 18 additions & 7 deletions src/Metadata/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,37 @@ metadata(x) = nothing
metadata(x::SubArray) = metadata(parent(x))
metadata(x::Base.ReshapedArray) = metadata(parent(x))
# define our own metadata method
Metadata.metadata(x::MetadataArray) = getfield(x, :metadata)
metadata(A::NamedDimsArray) = metadata(parent(A))
metadata(A::AbstractAxisArray) = metadata(parent(A))
metadata(axis::AbstractAxis) = metadata(indices(axis))
metadata(A::MetadataArray) = getfield(A, :metadata)

"""
metaproperty(x, meta_key)
Return the metadata of `x` paired to `meta_key`.
"""
metaproperty(x, meta_key::Symbol) = getindex(metadata(x), meta_key)
@inline metaproperty(x, meta_key::Symbol) = _metaproperty(metadata(x), meta_key)
_metaproperty(x::AbstractDict{Symbol}, meta_key::Symbol) = getindex(x, meta_key)
_metaproperty(x, meta_key::Symbol) = getproperty(x, meta_key)

"""
metadata!(x, meta_key, val)
Set the metadata of `x` paired to `meta_key`.
"""
metaproperty!(x, meta_key::Symbol, val) = setindex!(metadata(x), val, meta_key)
@inline metaproperty!(x, meta_key::Symbol, val) = _metaproperty!(metadata(x), meta_key, val)
_metaproperty!(x::AbstractDict{Symbol}, meta_key::Symbol, val) = setindex!(x, val, meta_key)
_metaproperty!(x, meta_key::Symbol, val) = setproperty!(x, meta_key, val)

"""
has_metaproperty(x, meta_key) -> Bool
Returns true if `x` has a property in its metadata structure paired to `meta_key`.
"""
has_metaproperty(x, meta_key::Symbol) = haskey(metadata(x), meta_key)
@inline has_metaproperty(x, meta_key::Symbol) = _has_metaproperty(metadata(x), meta_key)
_has_metaproperty(x::AbstractDict{Symbol}, meta_key::Symbol) = haskey(x, meta_key)
_has_metaproperty(x, meta_key::Symbol) = hasproperty(x, meta_key)

"""
axis_meta(x)
Expand All @@ -67,22 +73,22 @@ axis_meta(x::AbstractArray, i) = metadata(axes(x, i))
Return the metadata of `x` paired to `meta_key` at axis `i`.
"""
axis_metaproperty(x, i, meta_key::Symbol) = getindex(axis_meta(x, i), meta_key)
axis_metaproperty(x, i, meta_key::Symbol) = _metaproperty(axis_meta(x, i), meta_key)

"""
axis_metaproperty!(x, meta_key, val)
Set the metadata of `x` paired to `meta_key` at axis `i`.
"""
axis_metaproperty!(x, i, meta_key::Symbol, val) = setindex!(axis_meta(x, i), val, meta_key)
axis_metaproperty!(x, i, meta_key::Symbol, val) = _metaproperty!(axis_meta(x, i), meta_key, val)

"""
has_axis_metaproperty(x, dim, meta_key)
Returns true if `x` has a property in its metadata structure paired to `meta_key` stored
at the axis corresponding to `dim`.
"""
has_axis_metaproperty(x, i, meta_key::Symbol) = haskey(axis_meta(x, i), meta_key)
has_axis_metaproperty(x, i, meta_key::Symbol) = _has_metaproperty(axis_meta(x, i), meta_key)

"""
has_metadata(x) -> Bool
Expand Down Expand Up @@ -118,6 +124,11 @@ function metadata_type(::Type{A}) where {A<:AbstractArray}
end
metadata_type(::Type{<:AbstractAxis{K,I,Ks,Inds}}) where {K,I,Ks,Inds} = metadata_type(Inds)

# This allows dictionaries's keys to be treated like property names
@inline metanames(x) = _metanames(metadata(x))
_metanames(m::AbstractDict) = keys(m)
_metanames(x) = propertynames(x)

# TODO document combine_metadata
function combine_metadata(x::AbstractUnitRange, y::AbstractUnitRange)
return combine_metadata(metadata(x), metadata(y))
Expand Down
1 change: 0 additions & 1 deletion src/PrettyArrays/PrettyArrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ using PrettyTables
using Base: tail

import NamedDims: NamedDimsArray
import MetadataArrays: MetadataArray

export
pretty_array,
Expand Down
3 changes: 1 addition & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@ using TableTraitsUtils
using MappedArrays
using Dates
using Documenter
import MetadataArrays

#=
pkgs = (MetadataArrays,Documenter,Dates,MappedArrays,Statistics,TableTraits,TableTraitsUtils,LinearAlgebra,Tables,IntervalSets,NamedDims,StaticRanges,StaticArrays,Base,Core);
pkgs = (Documenter,Dates,MappedArrays,Statistics,TableTraits,TableTraitsUtils,LinearAlgebra,Tables,IntervalSets,NamedDims,StaticRanges,StaticArrays,Base,Core);
ambs = detect_ambiguities(pkgs...);
using AxisIndices
ambs = setdiff(detect_ambiguities(AxisIndices, pkgs...), ambs);
Expand Down

2 comments on commit e5d5d9b

@Tokazama
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/18798

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.6.3 -m "<description of version>" e5d5d9bbacdc3d058581b564e4cdde46931e2c32
git push origin v0.6.3

Please sign in to comment.