From 99b8d9f004ae27e671ae48f787f0a009546c7e22 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 17 Jan 2026 03:54:38 +0000 Subject: [PATCH 1/7] Initial plan From 9c1ebe3c7f73211790f2f8a974cca5cce11dcb15 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 17 Jan 2026 04:03:40 +0000 Subject: [PATCH 2/7] Add JLD2 dependency and support in function form Co-authored-by: dahong67 <9384655+dahong67@users.noreply.github.com> --- Project.toml | 2 ++ src/CacheVariables.jl | 1 + src/function.jl | 24 ++++++++++++++++++++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index d94c8ad..2427a68 100644 --- a/Project.toml +++ b/Project.toml @@ -7,6 +7,7 @@ version = "0.2.0" BSON = "fbb218c0-5317-5bc6-957e-2ee96dd4b1f0" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" ExpressionExplorer = "21656369-7473-754a-2065-74616d696c43" +JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" @@ -14,6 +15,7 @@ MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" BSON = "0.3.4" Dates = "1.10" ExpressionExplorer = "1.1.3" +JLD2 = "0.4, 0.5" Logging = "1.10" MacroTools = "0.5.16" julia = "1.10" diff --git a/src/CacheVariables.jl b/src/CacheVariables.jl index 59604c2..7e14d69 100755 --- a/src/CacheVariables.jl +++ b/src/CacheVariables.jl @@ -3,6 +3,7 @@ module CacheVariables using BSON using Dates: UTC, now using ExpressionExplorer: compute_symbols_state +using JLD2 using Logging: @info using MacroTools: @capture diff --git a/src/function.jl b/src/function.jl index c0f4516..79ae2cc 100644 --- a/src/function.jl +++ b/src/function.jl @@ -6,6 +6,10 @@ Cache the output of running `f()` in a cache file at `path`. The output is loaded if the file exists and is saved otherwise. +The file format is determined by the file extension: +`.bson` for [BSON.jl](https://github.com/JuliaIO/BSON.jl) and +`.jld2` for [JLD2.jl](https://github.com/JuliaIO/JLD2.jl). + In addition to the output of `f()`, the following metadata is saved for the run: - Julia version - Time when run (in UTC) @@ -71,11 +75,27 @@ function cache(@nospecialize(f), path; overwrite = false, bson_mod = Main) # Save metadata and output mkpath(dirname(path)) - bson(path; version, whenrun, runtime, output) + if endswith(path, ".bson") + bson(path; version, whenrun, runtime, output) + elseif endswith(path, ".jld2") + JLD2.jldsave(path; version, whenrun, runtime, output) + else + error("Unsupported file extension for $path. Only .bson and .jld2 are supported.") + end return output else # Load metadata and output - (; version, whenrun, runtime, output) = NamedTuple(BSON.load(path, bson_mod)) + if endswith(path, ".bson") + (; version, whenrun, runtime, output) = NamedTuple(BSON.load(path, bson_mod)) + elseif endswith(path, ".jld2") + data = JLD2.load(path) + version = data["version"] + whenrun = data["whenrun"] + runtime = data["runtime"] + output = data["output"] + else + error("Unsupported file extension for $path. Only .bson and .jld2 are supported.") + end # Log @info message @info """ From de515ebbcf5b64dc05295a81ce2c4d4213a7b3df Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 17 Jan 2026 04:06:31 +0000 Subject: [PATCH 3/7] Add JLD2 tests and improve error handling Co-authored-by: dahong67 <9384655+dahong67@users.noreply.github.com> --- src/function.jl | 18 ++++-- test/runtests.jl | 164 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 176 insertions(+), 6 deletions(-) diff --git a/src/function.jl b/src/function.jl index 79ae2cc..f3ff112 100644 --- a/src/function.jl +++ b/src/function.jl @@ -58,6 +58,11 @@ function cache(@nospecialize(f), path; overwrite = false, bson_mod = Main) if isnothing(path) return f() elseif !ispath(path) || overwrite + # Validate file extension early + if !endswith(path, ".bson") && !endswith(path, ".jld2") + error("Unsupported file extension for $path. Only .bson and .jld2 are supported.") + end + # Collect metadata and run function version = VERSION whenrun = now(UTC) @@ -77,24 +82,25 @@ function cache(@nospecialize(f), path; overwrite = false, bson_mod = Main) mkpath(dirname(path)) if endswith(path, ".bson") bson(path; version, whenrun, runtime, output) - elseif endswith(path, ".jld2") + else # .jld2 JLD2.jldsave(path; version, whenrun, runtime, output) - else - error("Unsupported file extension for $path. Only .bson and .jld2 are supported.") end return output else + # Validate file extension early + if !endswith(path, ".bson") && !endswith(path, ".jld2") + error("Unsupported file extension for $path. Only .bson and .jld2 are supported.") + end + # Load metadata and output if endswith(path, ".bson") (; version, whenrun, runtime, output) = NamedTuple(BSON.load(path, bson_mod)) - elseif endswith(path, ".jld2") + else # .jld2 data = JLD2.load(path) version = data["version"] whenrun = data["whenrun"] runtime = data["runtime"] output = data["output"] - else - error("Unsupported file extension for $path. Only .bson and .jld2 are supported.") end # Log @info message diff --git a/test/runtests.jl b/test/runtests.jl index 7731dec..7fd01e3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -397,4 +397,168 @@ end end end +## Test JLD2 format - function form +@testitem "cache with JLD2 format" begin + using JLD2, Dates + mktempdir(@__DIR__; prefix = "temp_") do dirpath + jld2path = joinpath(dirpath, "jld2test.jld2") + + # 1. Verify log messages for saving + log1 = (:info, r"^Saved cached values to .+\.") + @test_logs log1 match_mode = :any cache(jld2path) do + x = collect(1:3) + y = 4 + z = "test" + return (; x = x, y = y, z = z) + end + + # 2. Delete cache and run again + rm(jld2path) + out = cache(jld2path) do + x = collect(1:3) + y = 4 + z = "test" + return (; x = x, y = y, z = z) + end + + # 3. Verify the output + @test out == (; x = [1, 2, 3], y = 4, z = "test") + + # 4. Reset the output + out = nothing + + # 5. Verify log messages for loading + log1 = (:info, r"^Loaded cached values from .+\.") + @test_logs log1 match_mode = :any cache(jld2path) do + x = collect(1:3) + y = 4 + z = "test" + return (; x = x, y = y, z = z) + end + + # 6. Load values from cache + out = cache(jld2path) do + x = collect(1:3) + y = 4 + z = "test" + return (; x = x, y = y, z = z) + end + + # 7. Verify the output + @test out == (; x = [1, 2, 3], y = 4, z = "test") + + # 8. Verify the metadata + data = JLD2.load(jld2path) + @test data["version"] isa VersionNumber + @test data["whenrun"] isa Dates.DateTime + @test data["runtime"] isa Real && data["runtime"] >= 0 + end +end + +## Test JLD2 format - macro form +@testitem "@cache with JLD2 format" begin + using JLD2 + mktempdir(@__DIR__; prefix = "temp_") do dirpath + jld2macropath = joinpath(dirpath, "jld2macro.jld2") + + # 1. Verify log messages for saving + log1 = (:info, "Variable assignments found: x, y, z") + log2 = (:info, r"^Saved cached values to .+\.") + @test_logs log1 log2 (@cache jld2macropath begin + x = collect(1:3) + y = 4 + z = "test" + "final output" + end) + + # 2. Delete cache and run again + rm(jld2macropath) + out = @cache jld2macropath begin + x = collect(1:3) + y = 4 + z = "test" + "final output" + end + + # 3. Verify that the variables enter the workspace correctly + @test x == [1, 2, 3] + @test y == 4 + @test z == "test" + @test out == "final output" + + # 4. Reset the variables + x = y = z = out = nothing + + # 5. Verify log messages for loading + log1 = (:info, "Variable assignments found: x, y, z") + log2 = (:info, r"^Loaded cached values from .+\.") + @test_logs log1 log2 (@cache jld2macropath begin + x = collect(1:3) + y = 4 + z = "test" + "final output" + end) + + # 6. Load variables + out = @cache jld2macropath begin + x = collect(1:3) + y = 4 + z = "test" + "final output" + end + + # 7. Verify that the variables enter the workspace correctly + @test x == [1, 2, 3] + @test y == 4 + @test z == "test" + @test out == "final output" + end +end + +## Test JLD2 format - in a module +@testitem "cache with JLD2 in a module" begin + module MyJLD2Module + using CacheVariables, Test, DataFrames + + mktempdir(@__DIR__; prefix = "temp_") do dirpath + modpath = joinpath(dirpath, "jld2modtest.jld2") + + # 1. Save and check the output + out = cache(modpath) do + return DataFrame(; a = 1:10, b = 'a':'j') + end + @test out == DataFrame(; a = 1:10, b = 'a':'j') + + # 2. Reset the output + out = nothing + + # 3. Load and check the output + out = cache(modpath) do + return DataFrame(; a = 1:10, b = 'a':'j') + end + @test out == DataFrame(; a = 1:10, b = 'a':'j') + end + end +end + +## Test error handling for unsupported file extensions +@testitem "unsupported file extensions" begin + mktempdir(@__DIR__; prefix = "temp_") do dirpath + # Test with function form + badpath = joinpath(dirpath, "test.txt") + @test_throws ErrorException("Unsupported file extension for $badpath. Only .bson and .jld2 are supported.") cache( + badpath, + ) do + 42 + end + + # Test with macro form + badpath2 = joinpath(dirpath, "test.mat") + @test_throws ErrorException("Unsupported file extension for $badpath2. Only .bson and .jld2 are supported.") @cache badpath2 begin + x = 1 + x + end + end +end + @run_package_tests From 0549eb51f96b56b00febe931530531d137e7f9c4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 17 Jan 2026 04:08:44 +0000 Subject: [PATCH 4/7] Add file formats section to README Co-authored-by: dahong67 <9384655+dahong67@users.noreply.github.com> --- README.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/README.md b/README.md index 54e5162..159afd2 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,51 @@ julia> a, b # b was overwritten in the first let block but not the second > This should generally work, but may not always catch all the variables - check the list > printed out to make sure. The function form `cache` can be used for more control. +## File formats + +CacheVariables.jl supports two file formats, determined by the file extension: + +- **BSON** (`.bson`): Use [BSON.jl](https://github.com/JuliaIO/BSON.jl) for serialization. This is a lightweight format that works well for most Julia objects. +- **JLD2** (`.jld2`): Use [JLD2.jl](https://github.com/JuliaIO/JLD2.jl) for serialization. This format provides better support for arbitrary Julia types, including `BigInt` and other types that may not work well with BSON. + +Simply change the file extension to switch between formats: + +```julia +# Using BSON format +cache("results.bson") do + # your computation +end + +# Using JLD2 format +cache("results.jld2") do + # your computation +end +``` + +The same applies to the macro form: + +```julia +# Using BSON format +@cache "results.bson" begin + # your code +end + +# Using JLD2 format +@cache "results.jld2" begin + # your code +end +``` + +For BSON files, you can pass the `bson_mod` keyword argument to specify the module context for loading: + +```julia +cache("data.bson"; bson_mod = @__MODULE__) do + # your computation +end +``` + +This can be useful when working in modules or in Pluto notebooks (see [BSON.jl documentation](https://github.com/JuliaIO/BSON.jl?tab=readme-ov-file#loading-custom-data-types-within-modules) for more details). + ## Caching the results of a sweep It can be common to need to cache the results of a large sweep (e.g., over parameters or trials of a simulation). From cf3757ae3ab9d69b7171f5a808338154bb2c8f6b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 17 Jan 2026 04:10:36 +0000 Subject: [PATCH 5/7] Refactor to eliminate duplicate validation code Co-authored-by: dahong67 <9384655+dahong67@users.noreply.github.com> --- src/function.jl | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/function.jl b/src/function.jl index f3ff112..5970e1d 100644 --- a/src/function.jl +++ b/src/function.jl @@ -1,5 +1,12 @@ # Function form +# Helper function to validate file extensions +function _validate_extension(path) + if !endswith(path, ".bson") && !endswith(path, ".jld2") + error("Unsupported file extension for $path. Only .bson and .jld2 are supported.") + end +end + """ cache(f, path; overwrite=false, bson_mod=Main) @@ -59,9 +66,7 @@ function cache(@nospecialize(f), path; overwrite = false, bson_mod = Main) return f() elseif !ispath(path) || overwrite # Validate file extension early - if !endswith(path, ".bson") && !endswith(path, ".jld2") - error("Unsupported file extension for $path. Only .bson and .jld2 are supported.") - end + _validate_extension(path) # Collect metadata and run function version = VERSION @@ -88,9 +93,7 @@ function cache(@nospecialize(f), path; overwrite = false, bson_mod = Main) return output else # Validate file extension early - if !endswith(path, ".bson") && !endswith(path, ".jld2") - error("Unsupported file extension for $path. Only .bson and .jld2 are supported.") - end + _validate_extension(path) # Load metadata and output if endswith(path, ".bson") From d88b4347dccbdb3a8bc724c52db4a195c394d33d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 17 Jan 2026 04:13:30 +0000 Subject: [PATCH 6/7] Use explicit extension checks for improved safety Co-authored-by: dahong67 <9384655+dahong67@users.noreply.github.com> --- src/function.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/function.jl b/src/function.jl index 5970e1d..ce4cc2d 100644 --- a/src/function.jl +++ b/src/function.jl @@ -87,7 +87,7 @@ function cache(@nospecialize(f), path; overwrite = false, bson_mod = Main) mkpath(dirname(path)) if endswith(path, ".bson") bson(path; version, whenrun, runtime, output) - else # .jld2 + elseif endswith(path, ".jld2") JLD2.jldsave(path; version, whenrun, runtime, output) end return output @@ -98,7 +98,7 @@ function cache(@nospecialize(f), path; overwrite = false, bson_mod = Main) # Load metadata and output if endswith(path, ".bson") (; version, whenrun, runtime, output) = NamedTuple(BSON.load(path, bson_mod)) - else # .jld2 + elseif endswith(path, ".jld2") data = JLD2.load(path) version = data["version"] whenrun = data["whenrun"] From 80e59683db320599a3d584def64d7c9728a5f104 Mon Sep 17 00:00:00 2001 From: David Hong Date: Sat, 17 Jan 2026 01:05:30 -0500 Subject: [PATCH 7/7] Review and revise PR --- README.md | 24 +++++++------ src/CacheVariables.jl | 4 +-- src/function.jl | 66 ++++++++++++++++++++---------------- test/runtests.jl | 78 ++++++++++++++++++++----------------------- 4 files changed, 90 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 159afd2..e5ac56e 100644 --- a/README.md +++ b/README.md @@ -172,46 +172,50 @@ julia> a, b # b was overwritten in the first let block but not the second CacheVariables.jl supports two file formats, determined by the file extension: -- **BSON** (`.bson`): Use [BSON.jl](https://github.com/JuliaIO/BSON.jl) for serialization. This is a lightweight format that works well for most Julia objects. -- **JLD2** (`.jld2`): Use [JLD2.jl](https://github.com/JuliaIO/JLD2.jl) for serialization. This format provides better support for arbitrary Julia types, including `BigInt` and other types that may not work well with BSON. +- `.bson`: save using [BSON.jl](https://github.com/JuliaIO/BSON.jl), + which is a lightweight format that works well for many Julia objects. +- `.jld2`: save using [JLD2.jl](https://github.com/JuliaIO/JLD2.jl), + which may provide better support for arbitrary Julia types. Simply change the file extension to switch between formats: ```julia # Using BSON format cache("results.bson") do - # your computation + # cached computations end # Using JLD2 format cache("results.jld2") do - # your computation + # cached computations end ``` -The same applies to the macro form: +The same works for the macro form: ```julia # Using BSON format @cache "results.bson" begin - # your code + # cached computations end # Using JLD2 format @cache "results.jld2" begin - # your code + # cached computations end ``` -For BSON files, you can pass the `bson_mod` keyword argument to specify the module context for loading: +The module context for loading BSON files can be set via the `bson_mod` keyword argument: ```julia cache("data.bson"; bson_mod = @__MODULE__) do - # your computation + # cached computations end ``` -This can be useful when working in modules or in Pluto notebooks (see [BSON.jl documentation](https://github.com/JuliaIO/BSON.jl?tab=readme-ov-file#loading-custom-data-types-within-modules) for more details). +This may be useful when working in modules or in Pluto notebooks +(see the [BSON.jl documentation](https://github.com/JuliaIO/BSON.jl?tab=readme-ov-file#loading-custom-data-types-within-modules) +for more detail). ## Caching the results of a sweep diff --git a/src/CacheVariables.jl b/src/CacheVariables.jl index 7e14d69..63fae7f 100755 --- a/src/CacheVariables.jl +++ b/src/CacheVariables.jl @@ -1,9 +1,9 @@ module CacheVariables -using BSON +using BSON: BSON using Dates: UTC, now using ExpressionExplorer: compute_symbols_state -using JLD2 +using JLD2: JLD2 using Logging: @info using MacroTools: @capture diff --git a/src/function.jl b/src/function.jl index ce4cc2d..f6f1134 100644 --- a/src/function.jl +++ b/src/function.jl @@ -1,30 +1,23 @@ # Function form -# Helper function to validate file extensions -function _validate_extension(path) - if !endswith(path, ".bson") && !endswith(path, ".jld2") - error("Unsupported file extension for $path. Only .bson and .jld2 are supported.") - end -end - """ cache(f, path; overwrite=false, bson_mod=Main) Cache the output of running `f()` in a cache file at `path`. The output is loaded if the file exists and is saved otherwise. -The file format is determined by the file extension: -`.bson` for [BSON.jl](https://github.com/JuliaIO/BSON.jl) and -`.jld2` for [JLD2.jl](https://github.com/JuliaIO/JLD2.jl). - In addition to the output of `f()`, the following metadata is saved for the run: - Julia version - Time when run (in UTC) - Runtime of code (in seconds) -If `path` is set to `nothing`, caching is disabled and `f()` is simply run. +The file extension of `path` determines the file format used: +`.bson` for [BSON.jl](https://github.com/JuliaIO/BSON.jl) and +`.jld2` for [JLD2.jl](https://github.com/JuliaIO/JLD2.jl). +The `path` can also be set to `nothing` to disable caching and simply run `f()`. This can be useful for conditionally caching the results, e.g., to only cache a sweep when the full set is ready. + If `overwrite` is set to true, existing cache files will be overwritten with the results (and metadata) from a "fresh" call to `f()`. If necessary, the module to use for BSON can be set with `bson_mod`. @@ -61,13 +54,14 @@ julia> cache(nothing) do (a = "a very time-consuming quantity to compute", b = "a very long simulation to run") ``` """ -function cache(@nospecialize(f), path; overwrite = false, bson_mod = Main) - if isnothing(path) - return f() - elseif !ispath(path) || overwrite - # Validate file extension early - _validate_extension(path) - +function cache(@nospecialize(f), path::AbstractString; overwrite = false, bson_mod = Main) + # Check file extension + ext = splitext(path)[2] + (ext == ".bson" || ext == ".jld2") || + throw(ArgumentError("Only `.bson` and `.jld2` files are supported.")) + + # Save, overwrite or load + if !ispath(path) || overwrite # Collect metadata and run function version = VERSION whenrun = now(UTC) @@ -85,20 +79,33 @@ function cache(@nospecialize(f), path; overwrite = false, bson_mod = Main) # Save metadata and output mkpath(dirname(path)) - if endswith(path, ".bson") - bson(path; version, whenrun, runtime, output) - elseif endswith(path, ".jld2") - JLD2.jldsave(path; version, whenrun, runtime, output) + if ext == ".bson" + data = Dict( + :version => version, + :whenrun => whenrun, + :runtime => runtime, + :output => output, + ) + BSON.bson(path, data) + elseif ext == ".jld2" + data = Dict( + "version" => version, + "whenrun" => whenrun, + "runtime" => runtime, + "output" => output, + ) + JLD2.save(path, data) end return output else - # Validate file extension early - _validate_extension(path) - # Load metadata and output - if endswith(path, ".bson") - (; version, whenrun, runtime, output) = NamedTuple(BSON.load(path, bson_mod)) - elseif endswith(path, ".jld2") + if ext == ".bson" + data = BSON.load(path, bson_mod) + version = data[:version] + whenrun = data[:whenrun] + runtime = data[:runtime] + output = data[:output] + elseif ext == ".jld2" data = JLD2.load(path) version = data["version"] whenrun = data["whenrun"] @@ -117,3 +124,4 @@ function cache(@nospecialize(f), path; overwrite = false, bson_mod = Main) return output end end +cache(@nospecialize(f), ::Nothing; kwargs...) = f() diff --git a/test/runtests.jl b/test/runtests.jl index 7fd01e3..8f32397 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,7 +1,7 @@ using TestItemRunner -## Test save and load behavior of @cache macro -@testitem "@cache save and load" begin +## Test save and load behavior of @cache macro with BSON format +@testitem "@cache save and load (BSON)" begin mktempdir(@__DIR__; prefix = "temp_") do dirpath path = joinpath(dirpath, "test.bson") @@ -302,8 +302,8 @@ end end end -## Test save and load behavior of cache function -@testitem "cache save and load" begin +## Test save and load behavior of cache function with BSON format +@testitem "cache save and load (BSON)" begin using BSON, Dates mktempdir(@__DIR__; prefix = "temp_") do dirpath funcpath = joinpath(dirpath, "functest.bson") @@ -341,7 +341,7 @@ end return (; x = x, y = y, z = z) end - # 6. Load output + # 6. Load the output out = cache(funcpath) do x = collect(1:3) y = 4 @@ -371,9 +371,9 @@ end @test out == (; x = [1, 2, 3], y = 4, z = "test") end -## Test cache in a module -@testitem "cache in a module" begin - module MyCacheModule +## Test cache in a module (BSON) +@testitem "cache in a module (BSON)" begin + module MyCacheModuleBSON using CacheVariables, Test, DataFrames mktempdir(@__DIR__; prefix = "temp_") do dirpath @@ -397,15 +397,15 @@ end end end -## Test JLD2 format - function form -@testitem "cache with JLD2 format" begin +## Test save and load behavior of cache function with JLD2 format +@testitem "cache save and load (JLD2)" begin using JLD2, Dates mktempdir(@__DIR__; prefix = "temp_") do dirpath - jld2path = joinpath(dirpath, "jld2test.jld2") + funcpath = joinpath(dirpath, "functest.jld2") # 1. Verify log messages for saving - log1 = (:info, r"^Saved cached values to .+\.") - @test_logs log1 match_mode = :any cache(jld2path) do + log = (:info, r"^Saved cached values to .+\.") + @test_logs log cache(funcpath) do x = collect(1:3) y = 4 z = "test" @@ -413,8 +413,8 @@ end end # 2. Delete cache and run again - rm(jld2path) - out = cache(jld2path) do + rm(funcpath) + out = cache(funcpath) do x = collect(1:3) y = 4 z = "test" @@ -428,16 +428,16 @@ end out = nothing # 5. Verify log messages for loading - log1 = (:info, r"^Loaded cached values from .+\.") - @test_logs log1 match_mode = :any cache(jld2path) do + log = (:info, r"^Loaded cached values from .+\.") + @test_logs log cache(funcpath) do x = collect(1:3) y = 4 z = "test" return (; x = x, y = y, z = z) end - # 6. Load values from cache - out = cache(jld2path) do + # 6. Load the output + out = cache(funcpath) do x = collect(1:3) y = 4 z = "test" @@ -448,23 +448,22 @@ end @test out == (; x = [1, 2, 3], y = 4, z = "test") # 8. Verify the metadata - data = JLD2.load(jld2path) + data = JLD2.load(funcpath) @test data["version"] isa VersionNumber @test data["whenrun"] isa Dates.DateTime @test data["runtime"] isa Real && data["runtime"] >= 0 end end -## Test JLD2 format - macro form -@testitem "@cache with JLD2 format" begin - using JLD2 +## Test save and load behavior of @cache macro with JLD2 format +@testitem "@cache save and load (JLD2)" begin mktempdir(@__DIR__; prefix = "temp_") do dirpath - jld2macropath = joinpath(dirpath, "jld2macro.jld2") + path = joinpath(dirpath, "test.jld2") # 1. Verify log messages for saving log1 = (:info, "Variable assignments found: x, y, z") log2 = (:info, r"^Saved cached values to .+\.") - @test_logs log1 log2 (@cache jld2macropath begin + @test_logs log1 log2 (@cache path begin x = collect(1:3) y = 4 z = "test" @@ -472,8 +471,8 @@ end end) # 2. Delete cache and run again - rm(jld2macropath) - out = @cache jld2macropath begin + rm(path) + out = @cache path begin x = collect(1:3) y = 4 z = "test" @@ -492,7 +491,7 @@ end # 5. Verify log messages for loading log1 = (:info, "Variable assignments found: x, y, z") log2 = (:info, r"^Loaded cached values from .+\.") - @test_logs log1 log2 (@cache jld2macropath begin + @test_logs log1 log2 (@cache path begin x = collect(1:3) y = 4 z = "test" @@ -500,7 +499,7 @@ end end) # 6. Load variables - out = @cache jld2macropath begin + out = @cache path begin x = collect(1:3) y = 4 z = "test" @@ -515,13 +514,13 @@ end end end -## Test JLD2 format - in a module -@testitem "cache with JLD2 in a module" begin - module MyJLD2Module +## Test cache in a module (JLD2) +@testitem "cache in a module (JLD2)" begin + module MyCacheModuleJLD2 using CacheVariables, Test, DataFrames mktempdir(@__DIR__; prefix = "temp_") do dirpath - modpath = joinpath(dirpath, "jld2modtest.jld2") + modpath = joinpath(dirpath, "funcmodtest.jld2") # 1. Save and check the output out = cache(modpath) do @@ -544,19 +543,16 @@ end ## Test error handling for unsupported file extensions @testitem "unsupported file extensions" begin mktempdir(@__DIR__; prefix = "temp_") do dirpath + badpath = joinpath(dirpath, "test.mat") + # Test with function form - badpath = joinpath(dirpath, "test.txt") - @test_throws ErrorException("Unsupported file extension for $badpath. Only .bson and .jld2 are supported.") cache( - badpath, - ) do - 42 + @test_throws ArgumentError cache(badpath) do + return 42 end # Test with macro form - badpath2 = joinpath(dirpath, "test.mat") - @test_throws ErrorException("Unsupported file extension for $badpath2. Only .bson and .jld2 are supported.") @cache badpath2 begin + @test_throws ArgumentError @cache badpath begin x = 1 - x end end end