Skip to content

Commit

Permalink
Various code cleanups; method reductions, removing unused code, etc. …
Browse files Browse the repository at this point in the history
…Mostly cherry-picked from #92 (#95)
  • Loading branch information
quinnj authored May 15, 2019
1 parent 5eced11 commit 950712d
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 35 deletions.
2 changes: 0 additions & 2 deletions src/Tables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ function __init__()
allocatecolumn(::Type{WeakRefString{T}}, rows) where {T} = StringVector(undef, rows)
allocatecolumn(::Type{Union{Missing, WeakRefString{T}}}, rows) where {T} =
StringVector{Union{Missing, String}}(undef, rows)
unweakref(wk::WeakRefString) = string(wk)
unweakreftype(::Type{<:WeakRefString}) = String
end
end

Expand Down
10 changes: 4 additions & 6 deletions src/fallbacks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,12 @@ function rows(x::T) where {T}
cols = columns(x)
return RowIterator(cols, rowcount(cols))
elseif IteratorInterfaceExtensions.isiterable(x)
return IteratorWrapper(IteratorInterfaceExtensions.getiterator(x))
return nondatavaluerows(x)
end
throw(ArgumentError("no default `Tables.rows` implementation for type: $T"))
end

# build columns from rows
haslength(L) = L isa Union{Base.HasShape, Base.HasLength}

"""
Tables.allocatecolumn(::Type{T}, len) => returns a column type (usually AbstractVector) w/ size to hold `len` elements
Expand All @@ -89,7 +87,7 @@ end

@inline function buildcolumns(schema, rowitr::T) where {T}
L = Base.IteratorSize(T)
len = haslength(L) ? length(rowitr) : 0
len = Base.haslength(L) ? length(rowitr) : 0
nt = allocatecolumns(schema, len)
for (i, row) in enumerate(rowitr)
eachcolumn(add!, schema, row, L, nt, i)
Expand Down Expand Up @@ -125,7 +123,7 @@ function buildcolumns(::Nothing, rowitr::T) where {T}
row, st = state
names = Tuple(propertynames(row))
L = Base.IteratorSize(T)
len = haslength(L) ? length(rowitr) : 0
len = Base.haslength(L) ? length(rowitr) : 0
sch = Schema(names, nothing)
columns = NamedTuple{names}(Tuple(Union{}[] for _ = 1:length(names)))
return _buildcolumns(rowitr, row, st, sch, L, columns, 1, len, Ref{Any}(columns))
Expand Down Expand Up @@ -163,7 +161,7 @@ Base.getproperty(x::CopiedColumns, nm::Symbol) = getproperty(source(x), nm)
elseif TableTraits.supports_get_columns_copy_using_missing(x)
return CopiedColumns(TableTraits.get_columns_copy_using_missing(x))
elseif IteratorInterfaceExtensions.isiterable(x)
iw = IteratorWrapper(IteratorInterfaceExtensions.getiterator(x))
iw = nondatavaluerows(x)
return CopiedColumns(buildcolumns(schema(iw), iw))
end
throw(ArgumentError("no default `Tables.columns` implementation for type: $T"))
Expand Down
17 changes: 6 additions & 11 deletions src/namedtuples.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
# Vector of NamedTuples
const RowTable{T} = Vector{T} where {T <: NamedTuple}

# RowTables can't support WeakRefStrings
unweakref(x) = x
unweakreftype(T) = T
Base.@pure unweakreftypes(::Type{T}) where {T <: Tuple} = Tuple{Any[unweakreftype(fieldtype(T, i)) for i = 1:fieldcount(T)]...}

# interface implementation
istable(::Type{<:RowTable}) = true
rowaccess(::Type{<:RowTable}) = true
Expand All @@ -19,25 +14,25 @@ struct NamedTupleIterator{S, T}
x::T
end
Base.IteratorEltype(::Type{<:NamedTupleIterator{S}}) where {S} = S === nothing ? Base.EltypeUnknown() : Base.HasEltype()
Base.eltype(rows::NamedTupleIterator{Schema{names, T}}) where {names, T} = NamedTuple{names, unweakreftypes(T)}
Base.eltype(rows::NamedTupleIterator{Schema{names, T}}) where {names, T} = NamedTuple{names, T}
Base.IteratorSize(::Type{NamedTupleIterator{S, T}}) where {S, T} = Base.IteratorSize(T)
Base.length(nt::NamedTupleIterator) = length(nt.x)
Base.size(nt::NamedTupleIterator) = (length(nt.x),)

function Base.iterate(rows::NamedTupleIterator{Schema{names, T}}, st=()) where {names, T}
if @generated
vals = Tuple(:(unweakref(getproperty(row, $(fieldtype(T, i)), $i, $(Meta.QuoteNode(names[i]))))) for i = 1:fieldcount(T))
vals = Tuple(:(getproperty(row, $(fieldtype(T, i)), $i, $(Meta.QuoteNode(names[i])))) for i = 1:fieldcount(T))
return quote
x = iterate(rows.x, st...)
x === nothing && return nothing
row, st = x
return $(NamedTuple{names, unweakreftypes(T)})(($(vals...),)), (st,)
return $(NamedTuple{names, T})(($(vals...),)), (st,)
end
else
x = iterate(rows.x, st...)
x === nothing && return nothing
row, st = x
return NamedTuple{names, unweakreftypes(T)}(Tuple(unweakref(getproperty(row, fieldtype(T, i), i, names[i])) for i = 1:fieldcount(T))), (st,)
return NamedTuple{names, T}(Tuple(getproperty(row, fieldtype(T, i), i, names[i]) for i = 1:fieldcount(T))), (st,)
end
end

Expand All @@ -47,7 +42,7 @@ function Base.iterate(rows::NamedTupleIterator{Nothing, T}, st=()) where {T}
x === nothing && return nothing
row, st = x
names = Tuple(propertynames(row))
return NamedTuple{names}(Tuple(unweakref(getproperty(row, nm)) for nm in names)), (st,)
return NamedTuple{names}(Tuple(getproperty(row, nm) for nm in names)), (st,)
end

namedtupleiterator(::Type{T}, rows::S) where {T <: NamedTuple, S} = rows
Expand Down Expand Up @@ -110,7 +105,7 @@ function ctappend(ct1::NamedTuple{N1, T1}, ct2::NamedTuple{N2, T2}) where {N1, T
return ct1
end
else
foreach(nm->append!(ct1[nm], ct2[nm]), nms)
foreach(nm->append!(ct1[nm], ct2[nm]), N1)
return ct1
end
end
Expand Down
21 changes: 8 additions & 13 deletions src/tofromdatavalues.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ nondatavaluetype(::Type{Union{}}) = Union{}
datavaluetype(::Type{T}) where {T} = T
datavaluetype(::Type{Union{}}) = Union{}

Base.@pure function nondatavaluetype(::Type{NT}) where {NT <: NamedTuple{names}} where {names}
Base.@pure function nondatavaluenamedtuple(::Type{NT}) where {NT <: NamedTuple{names}} where {names}
TT = Tuple{Any[ nondatavaluetype(fieldtype(NT, i)) for i = 1:fieldcount(NT) ]...}
return NamedTuple{names, TT}
end

Base.@pure function datavaluetype(::Tables.Schema{names, types}) where {names, types}
Base.@pure function datavaluenamedtuple(::Tables.Schema{names, types}) where {names, types}
TT = Tuple{Any[ datavaluetype(fieldtype(types, i)) for i = 1:fieldcount(types) ]...}
return NamedTuple{names, TT}
end
Expand All @@ -24,16 +24,18 @@ struct IteratorWrapper{S}
x::S
end

nondatavaluerows(x) = IteratorWrapper(x)
nondatavaluerows(x) = IteratorWrapper(IteratorInterfaceExtensions.getiterator(x))
Tables.istable(::Type{<:IteratorWrapper}) = true
Tables.rowaccess(::Type{<:IteratorWrapper}) = true
Tables.rows(x::IteratorWrapper) = x

function Tables.schema(dv::IteratorWrapper)
eT = eltype(dv.x)
(!(eT <: NamedTuple) || eT === Union{}) && return nothing
return Tables.Schema(nondatavaluetype(eT))
return Tables.Schema(nondatavaluenamedtuple(eT))
end

Base.IteratorEltype(::Type{IteratorWrapper{S}}) where {S} = Base.IteratorEltype(S)
Base.eltype(rows::IteratorWrapper) = IteratorRow{eltype(rows.x)}
Base.IteratorSize(::Type{IteratorWrapper{S}}) where {S} = Base.IteratorSize(S)
Base.length(rows::IteratorWrapper) = length(rows.x)
Expand Down Expand Up @@ -67,23 +69,16 @@ Base.propertynames(d::IteratorRow) = propertynames(getfield(d, 1))
struct DataValueRowIterator{NT, S}
x::S
end
DataValueRowIterator(::Type{NT}, x::S) where {NT <: NamedTuple, S} = DataValueRowIterator{NT, S}(x)

"Returns a DataValue-based NamedTuple-iterator"
DataValueRowIterator(::Type{Schema{names, types}}, x::S) where {names, types, S} = DataValueRowIterator{datavaluetype(NamedTuple{names, types}), S}(x)

function datavaluerows(x)
r = Tables.rows(x)
s = Tables.schema(r)
s === nothing && error("Schemaless sources cannot be passed to datavaluerows.")
return DataValueRowIterator(datavaluetype(s), r)
return DataValueRowIterator{datavaluenamedtuple(s), typeof(r)}(r)
end

_iteratorsize(x) = x
_iteratorsize(::Base.HasShape{1}) = Base.HasLength()

Base.eltype(rows::DataValueRowIterator{NT, S}) where {NT, S} = NT
Base.IteratorSize(::Type{DataValueRowIterator{NT, S}}) where {NT, S} = _iteratorsize(Base.IteratorSize(S))
Base.IteratorSize(::Type{DataValueRowIterator{NT, S}}) where {NT, S} = Base.IteratorSize(S)
Base.length(rows::DataValueRowIterator) = length(rows.x)

function Base.iterate(rows::DataValueRowIterator{NT, S}, st=()) where {NT <: NamedTuple{names}, S} where {names}
Expand Down
6 changes: 3 additions & 3 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -409,19 +409,19 @@ end
rt2 = collect(dv)
@test rt2[1] == (a = 1, b = DataValue{Float64}(4.0), c = "7")

ei = Tables.IteratorWrapper(QueryOperators.EnumerableIterable{eltype(dv), typeof(dv)}(dv))
ei = Tables.nondatavaluerows(QueryOperators.EnumerableIterable{eltype(dv), typeof(dv)}(dv))
nt = ei |> columntable
@test isequal(rt, nt)
rt3 = ei |> rowtable
@test isequal(rt |> rowtable, rt3)

# rt = [(a=1, b=4.0, c="7"), (a=2, b=5.0, c="8"), (a=3, b=6.0, c="9")]
mt = Tables.IteratorWrapper(ei.x |> y->QueryOperators.map(y, x->(a=x.b, c=x.c), Expr(:block)))
mt = Tables.nondatavaluerows(ei.x |> y->QueryOperators.map(y, x->(a=x.b, c=x.c), Expr(:block)))
@inferred (mt |> columntable)
@inferred (mt |> rowtable)

# uninferrable case
mt = Tables.IteratorWrapper(ei.x |> y->QueryOperators.map(y, x->(a=x.a, c=x.c), Expr(:block)))
mt = Tables.nondatavaluerows(ei.x |> y->QueryOperators.map(y, x->(a=x.a, c=x.c), Expr(:block)))
@test (mt |> columntable) == (a = Real[1, 2.0, 3], c = ["7", "8", "9"])
@test length(mt |> rowtable) == 3

Expand Down

0 comments on commit 950712d

Please sign in to comment.