Skip to content

Commit

Permalink
Add Tables.isrowtable for convenience. Fixes #134
Browse files Browse the repository at this point in the history
  • Loading branch information
quinnj committed Feb 8, 2020
1 parent 10a2817 commit eeb255a
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 3 deletions.
26 changes: 23 additions & 3 deletions src/Tables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,27 @@ columnaccess(::Type{<:AbstractColumns}) = true
columns(x::AbstractColumns) = x
schema(x::AbstractColumns) = nothing

# default definitions
"""
Tables.isrowtable(x) => Bool
For convenience, some table objects that are naturally "row oriented" can
define `Tables.isrowtable(::Type{TableType}) = true` to simplify satisfying the
Tables.jl interface. Requirements for defining `isrowtable` include:
* `Tables.rows(x) === x`, i.e. the table object itself is a `Row` iterator
* If the table object is mutable, it should support:
* `push!(x, row)`: allow pushing a single row onto table
* `append!(x, rows)`: allow appending set of rows onto table
* If table object is mutable and indexable, it should support:
* `x[i] = row`: allow replacing of a row with another row by index
A table object that defines `Tables.isrowtable` will have definitions for
`Tables.istable`, `Tables.rowaccess`, and `Tables.rows` automatically defined.
"""
function isrowtable end

isrowtable(::T) where {T} = isrowtable(T)
isrowtable(::Type{T}) where {T} = false

"""
Tables.istable(x) => Bool
Expand All @@ -220,7 +240,7 @@ of knowing that the generator is a table.
function istable end

istable(x::T) where {T} = istable(T) || TableTraits.isiterabletable(x) === true
istable(::Type{T}) where {T} = false
istable(::Type{T}) where {T} = isrowtable(T)

"""
Tables.rowaccess(x) => Bool
Expand All @@ -239,7 +259,7 @@ natural for them to *consume* instead of worrying about what and how the input p
function rowaccess end

rowaccess(x::T) where {T} = rowaccess(T)
rowaccess(::Type{T}) where {T} = false
rowaccess(::Type{T}) where {T} = isrowtable(T)

"""
Tables.columnaccess(x) => Bool
Expand Down
1 change: 1 addition & 0 deletions src/fallbacks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ end

# this is our generic Tables.rows fallback definition
function rows(x::T) where {T}
isrowtable(x) && return x
# because this method is being called, we know `x` didn't define it's own Tables.rows
# first check if it supports column access, and if so, wrap it in a RowIterator
if columnaccess(T)
Expand Down
21 changes: 21 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -741,3 +741,24 @@ Tables.columnnames(r::Columns) = fieldnames(Columns)
@test Tables.schema(col) === nothing
@test isequal(Tables.columntable(col), ct)
end

struct IsRowTable
rows::Vector{NamedTuple}
end

Base.iterate(x::IsRowTable) = iterate(x.rows)
Base.iterate(x::IsRowTable, st) = iterate(x.rows, st)
Base.length(x::IsRowTable) = length(x.rows)

Tables.isrowtable(::Type{IsRowTable}) = true

@testset "Tables.isrowtable" begin

nt = (a=1, b=3.14, c="hey")
rt = IsRowTable([nt, nt, nt])
@test Tables.istable(rt)
@test Tables.rowaccess(rt)
@test Tables.rows(rt) === rt
@test Tables.columntable(rt) == Tables.columntable([nt, nt, nt])

end

0 comments on commit eeb255a

Please sign in to comment.