From d2f3982e831b2be3091db3d2ed9b765afc0cd6ab Mon Sep 17 00:00:00 2001 From: Peter Deffebach Date: Fri, 28 Jun 2024 20:26:26 -0400 Subject: [PATCH] progress --- src/parsing.jl | 35 +++++++++++++++++++++++------------ test/keyword_arguments.jl | 24 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/parsing.jl b/src/parsing.jl index 00bff676..e2da6852 100644 --- a/src/parsing.jl +++ b/src/parsing.jl @@ -499,22 +499,35 @@ end function get_df_args_kwargs(x, args...; wrap_byrow = false) kw = [] + # x is normally a data frame. But if the call looks like + # transform(df, :x = 1; copycols = false) + # then x is actually Expr(:parameters, Expr(:kw, :copycole, false)) + # When this happens, we assign x to the data frame, use only + # the rest of the args, and keep trask of the keyword argument. if x isa Expr && x.head === :parameters append!(kw, x.args) x = first(args) args = args[2:end] end - transforms, outer_flags, kw = create_args_vector!(kw, args...; wrap_byrow = wrap_byrow) + if args isa Tuple + blockarg = Expr(:block, args...) + else + blockarg = args + end - return (x, transforms, outer_flags, kw) -end + # create_args_vector! has an exclamation point because + # we modify the keyword arguments kw + transforms, outer_flags, kw = create_args_vector!(kw, blockarg; wrap_byrow = wrap_byrow) -function create_args_vector!(kw, args...; wrap_byrow::Bool=false) - create_args_vector!(kw, Expr(:block, args...); wrap_byrow = wrap_byrow) + return (x, transforms, outer_flags, kw) end function get_kw_from_macro_call(e::Expr) + if length(e.args) != 3 + throw(ArgumentError("Invalid @kwarg expression")) + end + nv = e.args[3] return nv @@ -532,8 +545,6 @@ the block as an array. If a simple expression, wrap the expression in a one-element vector. """ function create_args_vector!(kw, arg; wrap_byrow::Bool=false) - # TODO: Pass vector of keyword arguments to this function - # and modify by detecting presence of `@kwarg`. arg, outer_flags = extract_macro_flags(MacroTools.unblock(arg)) if wrap_byrow @@ -549,16 +560,16 @@ function create_args_vector!(kw, arg; wrap_byrow::Bool=false) if arg isa Expr && arg.head == :block && !outer_flags[ASTABLE_SYM][] x = MacroTools.rmlines(arg).args transforms = [] - seen_kw = !isempty(kw) + seen_kw_macro = false for xi in x if is_macro_head(xi, "@kwarg") - if seen_kw - throw(ArgumentError("@kwarg calls must be at end of block")) - end kw_item = get_kw_from_macro_call(xi) push!(kw, kw_item) - seen_kw = true + seen_kw_macro = true else + if seen_kw_macro + throw(ArgumentError("@kwarg calls must be at end of block")) + end push!(transforms, xi) end end diff --git a/test/keyword_arguments.jl b/test/keyword_arguments.jl index 2d7dd149..0c3116eb 100644 --- a/test/keyword_arguments.jl +++ b/test/keyword_arguments.jl @@ -401,4 +401,28 @@ end @test df2 == correct end +@testset "Multiple arguments #399" begin + correct = df[df.a .== 1, :] + correct_view = view(df, df.a .== 1, :) + + df2 = @subset(df, :a .== 1, :b .== 3; view = true) + @test df2 ≈ correct_view + + @test_throws ArgumentError @subset(df, :a .== 1, :b .== 3; skipmissing = false) + @test_throws ArgumentError @subset(df, :a .== 1, :b .== 3; skipmissing = false, view = true) + + correct = transform(df, :a => ByRow(t -> t + 1) => :y, :b => ByRow(t -> t + 2) => :z) + df2 = @rtransform(df, :y = :a + 1, :z = :b + 2; copycols = false) + @test df2 ≅ correct + @test df.a === df2.a + + correct = DataFrame(b_mean = [3.5, 5.0], b_first = [3, 5]) + df2 = @combine(gd, :b_mean = mean(skipmissing(:b)), :b_first = first(:b); keepkeys = false) + @test df2 ≅ correct +end + +@testset "@kwarg errors" begin + +end + end # module \ No newline at end of file