From d027be79f36e366c4c812a31d765c6feb0daf6c7 Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Fri, 28 Aug 2026 18:04:24 -0700 Subject: [PATCH 1/4] Migrate to test item framework Migrate tests and CI to the test item framework, remove PkgButler, bump min Julia to 1.12, and modernize repo infrastructure. Co-Authored-By: Claude Fable 5 --- .github/dependabot.yml | 10 +++ .../workflows/jlpkgbutler-butler-workflow.yml | 20 ------ .../jlpkgbutler-ci-master-workflow.yml | 40 ----------- .../workflows/jlpkgbutler-ci-pr-workflow.yml | 38 ---------- .../jlpkgbutler-codeformat-pr-workflow.yml | 21 ------ .../jlpkgbutler-compathelper-workflow.yml | 19 ----- .../jlpkgbutler-docdeploy-workflow.yml | 21 ------ .../workflows/jlpkgbutler-tagbot-workflow.yml | 13 ---- .github/workflows/juliaci.yml | 17 +++++ .gitignore | 4 ++ .jlpkgbutler.toml | 1 - LICENSE.md | 2 +- Project.toml | 11 +-- README.md | 3 +- docs/Project.toml | 2 +- docs/make.jl | 3 +- test/runtests.jl | 71 +------------------ test/test_statfiles.jl | 64 +++++++++++++++++ 18 files changed, 109 insertions(+), 251 deletions(-) create mode 100644 .github/dependabot.yml delete mode 100644 .github/workflows/jlpkgbutler-butler-workflow.yml delete mode 100644 .github/workflows/jlpkgbutler-ci-master-workflow.yml delete mode 100644 .github/workflows/jlpkgbutler-ci-pr-workflow.yml delete mode 100644 .github/workflows/jlpkgbutler-codeformat-pr-workflow.yml delete mode 100644 .github/workflows/jlpkgbutler-compathelper-workflow.yml delete mode 100644 .github/workflows/jlpkgbutler-docdeploy-workflow.yml delete mode 100644 .github/workflows/jlpkgbutler-tagbot-workflow.yml create mode 100644 .github/workflows/juliaci.yml delete mode 100644 .jlpkgbutler.toml create mode 100644 test/test_statfiles.jl diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..4e00cd8 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "julia" + directory: "/" + schedule: + interval: "weekly" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" \ No newline at end of file diff --git a/.github/workflows/jlpkgbutler-butler-workflow.yml b/.github/workflows/jlpkgbutler-butler-workflow.yml deleted file mode 100644 index f7894d9..0000000 --- a/.github/workflows/jlpkgbutler-butler-workflow.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Run the Julia Package Butler - -on: - push: - branches: - - master - schedule: - - cron: '0 */1 * * *' - -jobs: - butler: - name: "Run Package Butler" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: davidanthoff/julia-pkgbutler@releases/v1 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - ssh-private-key: ${{ secrets.JLPKGBUTLER_TOKEN }} - channel: stable diff --git a/.github/workflows/jlpkgbutler-ci-master-workflow.yml b/.github/workflows/jlpkgbutler-ci-master-workflow.yml deleted file mode 100644 index 0615a7e..0000000 --- a/.github/workflows/jlpkgbutler-ci-master-workflow.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Run CI on master - -on: - push: - branches: - - master - -jobs: - test: - runs-on: ${{ matrix.os }} - strategy: - matrix: - julia-version: ['1.0', '1.1', '1.2', '1.3', '1.4', '1.5'] - julia-arch: [x64, x86] - os: [ubuntu-latest, windows-latest, macOS-latest] - exclude: - - os: macOS-latest - julia-arch: x86 - - steps: - - uses: actions/checkout@v2 - - uses: julia-actions/setup-julia@latest - with: - version: ${{ matrix.julia-version }} - arch: ${{ matrix.julia-arch }} - - uses: julia-actions/julia-buildpkg@latest - env: - PYTHON: "" - - uses: julia-actions/julia-runtest@latest - env: - PYTHON: "" - - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v1 - with: - file: ./lcov.info - flags: unittests - name: codecov-umbrella - fail_ci_if_error: false - token: ${{ secrets.CODECOV_TOKEN }} - \ No newline at end of file diff --git a/.github/workflows/jlpkgbutler-ci-pr-workflow.yml b/.github/workflows/jlpkgbutler-ci-pr-workflow.yml deleted file mode 100644 index a47670e..0000000 --- a/.github/workflows/jlpkgbutler-ci-pr-workflow.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Run CI on PR - -on: - pull_request: - types: [opened, synchronize, reopened] - -jobs: - test: - runs-on: ${{ matrix.os }} - strategy: - matrix: - julia-version: ['1.0', '1.1', '1.2', '1.3', '1.4', '1.5'] - julia-arch: [x64, x86] - os: [ubuntu-latest, windows-latest, macOS-latest] - exclude: - - os: macOS-latest - julia-arch: x86 - - steps: - - uses: actions/checkout@v2 - - uses: julia-actions/setup-julia@latest - with: - version: ${{ matrix.julia-version }} - arch: ${{ matrix.julia-arch }} - - uses: julia-actions/julia-buildpkg@latest - env: - PYTHON: "" - - uses: julia-actions/julia-runtest@latest - env: - PYTHON: "" - - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v1 - with: - file: ./lcov.info - flags: unittests - name: codecov-umbrella - fail_ci_if_error: false - token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/jlpkgbutler-codeformat-pr-workflow.yml b/.github/workflows/jlpkgbutler-codeformat-pr-workflow.yml deleted file mode 100644 index f1252a0..0000000 --- a/.github/workflows/jlpkgbutler-codeformat-pr-workflow.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Code Formatting - -on: - push: - branches: - - master - -jobs: - format: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: julia-actions/julia-codeformat@releases/v1 - - name: Create Pull Request - uses: peter-evans/create-pull-request@v2 - with: - token: ${{ secrets.GITHUB_TOKEN }} - commit-message: Format files using DocumentFormat - title: '[AUTO] Format files using DocumentFormat' - body: '[DocumentFormat.jl](https://github.com/julia-vscode/DocumentFormat.jl) would suggest these formatting changes' - labels: no changelog diff --git a/.github/workflows/jlpkgbutler-compathelper-workflow.yml b/.github/workflows/jlpkgbutler-compathelper-workflow.yml deleted file mode 100644 index e41d211..0000000 --- a/.github/workflows/jlpkgbutler-compathelper-workflow.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Run CompatHelper - -on: - schedule: - - cron: '00 * * * *' - issues: - types: [opened, reopened] - -jobs: - compathelper: - name: "Run CompatHelper.jl" - runs-on: ubuntu-latest - steps: - - name: Pkg.add("CompatHelper") - run: julia -e 'using Pkg; Pkg.add("CompatHelper")' - - name: CompatHelper.main() - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: julia -e 'using CompatHelper; CompatHelper.main()' diff --git a/.github/workflows/jlpkgbutler-docdeploy-workflow.yml b/.github/workflows/jlpkgbutler-docdeploy-workflow.yml deleted file mode 100644 index de5c6b9..0000000 --- a/.github/workflows/jlpkgbutler-docdeploy-workflow.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Deploy documentation - -on: - push: - branches: - - master - tags: - - v* - -jobs: - docdeploy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: julia-actions/julia-buildpkg@latest - env: - PYTHON: "" - - uses: julia-actions/julia-docdeploy@releases/v1 - env: - DOCUMENTER_KEY: ${{ secrets.JLPKGBUTLER_TOKEN }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/jlpkgbutler-tagbot-workflow.yml b/.github/workflows/jlpkgbutler-tagbot-workflow.yml deleted file mode 100644 index 8c6b404..0000000 --- a/.github/workflows/jlpkgbutler-tagbot-workflow.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: TagBot -on: - schedule: - - cron: 0 * * * * -jobs: - TagBot: - runs-on: ubuntu-latest - steps: - - uses: JuliaRegistries/TagBot@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - ssh: ${{ secrets.JLPKGBUTLER_TOKEN }} - branches: true diff --git a/.github/workflows/juliaci.yml b/.github/workflows/juliaci.yml new file mode 100644 index 0000000..6aa24b5 --- /dev/null +++ b/.github/workflows/juliaci.yml @@ -0,0 +1,17 @@ +name: Julia CI + +on: + push: {branches: [main,master]} + pull_request: {types: [opened,synchronize,reopened,ready_for_review,converted_to_draft]} + issue_comment: {types: [created]} + workflow_dispatch: {inputs: {feature: {type: choice, description: What to run, options: [DocDeploy,LintAndTest,TagBot]}}} + +jobs: + julia-ci: + uses: julia-testitems/testitem-workflow/.github/workflows/juliaci.yml@v2 + with: + include-all-compatible-minor-versions: true + include-rc-versions: true + permissions: write-all + secrets: + codecov_token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.gitignore b/.gitignore index 6ee59bc..8534007 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,7 @@ *.jl.*.cov *.jl.mem .vscode +docs/build/ +docs/Manifest.toml +test-output*.* +Manifest.toml diff --git a/.jlpkgbutler.toml b/.jlpkgbutler.toml deleted file mode 100644 index b72304f..0000000 --- a/.jlpkgbutler.toml +++ /dev/null @@ -1 +0,0 @@ -template = "bach" diff --git a/LICENSE.md b/LICENSE.md index b9fb8c4..aa58615 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ The StatFiles.jl package is licensed under the MIT "Expat" License: -> Copyright (c) 2017-2019: David Anthoff. +> Copyright (c) 2017-2026: David Anthoff. > > > Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/Project.toml b/Project.toml index 7758f8b..bc43f02 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "StatFiles" uuid = "1463e38c-9381-5320-bcd4-4134955f093a" -version = "0.8.1-DEV" +version = "0.9.0-DEV" [deps] DataValues = "e7dc6d0d-1eca-5fa6-8ad6-5aecde8b7ea5" @@ -13,18 +13,19 @@ TableTraits = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" TableTraitsUtils = "382cd787-c1b6-5bf2-a167-d5b971a19bda" [extras] +TestItemRunner = "f8b46487-2199-4994-9208-9a1283c18c0a" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test"] +test = ["Test", "TestItemRunner"] [compat] -DataValues = "0.4.4" +DataValues = "0.4.4, 0.5" FileIO = "1" IterableTables = "0.8.3, 0.9, 0.10, 0.11, 1" IteratorInterfaceExtensions = "0.1.1, 1" ReadStat = "0.4.1, 1" -TableShowUtils = "0.1.1, 0.2" +TableShowUtils = "0.1.1, 0.2, 0.3" TableTraits = "0.3.1, 0.4, 1" TableTraitsUtils = "0.2.1, 0.3, 0.4, 1" -julia = "1" +julia = "1.12" diff --git a/README.md b/README.md index 76494b5..a5e1176 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ # StatFiles [![Project Status: Active - The project has reached a stable, usable state and is being actively developed.](http://www.repostatus.org/badges/latest/active.svg)](http://www.repostatus.org/#active) -[![Build Status](https://travis-ci.org/queryverse/StatFiles.jl.svg?branch=master)](https://travis-ci.org/queryverse/StatFiles.jl) -[![Build status](https://ci.appveyor.com/api/projects/status/lx7qmion1a8dggls/branch/master?svg=true)](https://ci.appveyor.com/project/queryverse/statfiles-jl/branch/master) +[![Build Status](https://github.com/queryverse/StatFiles.jl/actions/workflows/juliaci.yml/badge.svg?branch=main)](https://github.com/queryverse/StatFiles.jl/actions/workflows/juliaci.yml) [![codecov.io](http://codecov.io/github/queryverse/StatFiles.jl/coverage.svg?branch=master)](http://codecov.io/github/queryverse/StatFiles.jl?branch=master) ## Overview diff --git a/docs/Project.toml b/docs/Project.toml index f2a273e..1814eb3 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -2,4 +2,4 @@ Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" [compat] -Documenter = "~0.24" +Documenter = "1" diff --git a/docs/make.jl b/docs/make.jl index 047f96b..6e16a14 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -3,7 +3,8 @@ using Documenter, StatFiles makedocs( modules = [StatFiles], sitename = "StatFiles.jl", - analytics="UA-132838790-1", + format = Documenter.HTML(analytics = "UA-132838790-1"), + warnonly = [:missing_docs], pages = [ "Introduction" => "index.md" ] diff --git a/test/runtests.jl b/test/runtests.jl index 3fcb02b..01b84ea 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,70 +1,5 @@ -using StatFiles -using IteratorInterfaceExtensions -using TableTraits -using DataValues -using Test +using TestItemRunner -@testset "StatFiles" begin +include("test_statfiles.jl") -ar = load("types.dta") |> IteratorInterfaceExtensions.getiterator |> collect - -@test length(ar) == 3 -@test ar[1] == (vfloat=DataValue{Float32}(3.14), vdouble=DataValue(3.14), vlong=DataValue{Int32}(2), vint=DataValue{Int16}(2), vbyte=DataValue{Int8}(2), vstring=DataValue("2")) -@test ar[2] == (vfloat=DataValue{Float32}(7.), vdouble=DataValue(7.), vlong=DataValue{Int32}(7), vint=DataValue{Int16}(7), vbyte=DataValue{Int8}(7), vstring=DataValue("7")) -@test ar[3] == (vfloat=DataValue{Float32}(), vdouble=DataValue{Float64}(), vlong=DataValue{Int32}(), vint=DataValue{Int16}(), vbyte=DataValue{Int8}(), vstring=DataValue("")) -@test TableTraits.isiterabletable(load("types.dta")) == true -@test IteratorInterfaceExtensions.isiterable(load("types.dta")) == true - -ar = load("types.sas7bdat") |> IteratorInterfaceExtensions.getiterator |> collect - -@test length(ar) == 3 -@test ar[1] == (vfloat=DataValue{Float32}(3.14), vdouble=DataValue(3.14), vlong=DataValue{Int32}(2), vint=DataValue{Int16}(2), vbyte=DataValue{Int8}(2), vstring=DataValue("2")) -@test ar[2] == (vfloat=DataValue{Float32}(7.), vdouble=DataValue(7.), vlong=DataValue{Int32}(7), vint=DataValue{Int16}(7), vbyte=DataValue{Int8}(7), vstring=DataValue("7")) -@test ar[3] == (vfloat=DataValue{Float32}(), vdouble=DataValue{Float64}(), vlong=DataValue{Int32}(), vint=DataValue{Int16}(), vbyte=DataValue{Int8}(), vstring=DataValue("")) -@test TableTraits.isiterabletable(load("types.sas7bdat")) == true -@test IteratorInterfaceExtensions.isiterable(load("types.sas7bdat")) == true - -ar = load("types.sav") |> IteratorInterfaceExtensions.getiterator |> collect - -@test length(ar) == 3 -@test ar[1] == (vfloat=DataValue{Float32}(3.14), vdouble=DataValue(3.14), vlong=DataValue{Int32}(2), vint=DataValue{Int16}(2), vbyte=DataValue{Int8}(2), vstring=DataValue("2")) -@test ar[2] == (vfloat=DataValue{Float32}(7.), vdouble=DataValue(7.), vlong=DataValue{Int32}(7), vint=DataValue{Int16}(7), vbyte=DataValue{Int8}(7), vstring=DataValue("7")) -@test ar[3] == (vfloat=DataValue{Float32}(), vdouble=DataValue{Float64}(), vlong=DataValue{Int32}(), vint=DataValue{Int16}(), vbyte=DataValue{Int8}(), vstring=DataValue("")) -@test TableTraits.isiterabletable(load("types.sav")) == true -@test IteratorInterfaceExtensions.isiterable(load("types.sav")) == true - -end - -@testset "Show" begin - -ar = load("types.dta") - -@test sprint((stream,data)->show(stream, "text/html", data), ar) == "
vfloatvdoublevlongvintvbytevstring
3.143.14222"2"
7.07.0777"7"
#NA#NA#NA#NA#NA""
" -@test sprint((stream,data)->show(stream, "application/vnd.dataresource+json", data), ar) == -"{\"schema\":{\"fields\":[{\"name\":\"vfloat\",\"type\":\"number\"},{\"name\":\"vdouble\",\"type\":\"number\"},{\"name\":\"vlong\",\"type\":\"integer\"},{\"name\":\"vint\",\"type\":\"integer\"},{\"name\":\"vbyte\",\"type\":\"integer\"},{\"name\":\"vstring\",\"type\":\"string\"}]},\"data\":[{\"vfloat\":3.14,\"vdouble\":3.14,\"vlong\":2,\"vint\":2,\"vbyte\":2,\"vstring\":\"2\"},{\"vfloat\":7.0,\"vdouble\":7.0,\"vlong\":7,\"vint\":7,\"vbyte\":7,\"vstring\":\"7\"},{\"vfloat\":null,\"vdouble\":null,\"vlong\":null,\"vint\":null,\"vbyte\":null,\"vstring\":\"\"}]}" -@test sprint(show, ar) == "3x6 STATA file\nvfloat │ vdouble │ vlong │ vint │ vbyte │ vstring\n───────┼─────────┼───────┼──────┼───────┼────────\n3.14 │ 3.14 │ 2 │ 2 │ 2 │ \"2\" \n7.0 │ 7.0 │ 7 │ 7 │ 7 │ \"7\" \n#NA │ #NA │ #NA │ #NA │ #NA │ \"\" " - -@test showable("text/html", ar) == true -@test showable("application/vnd.dataresource+json", ar) == true - -ar = load("types.sas7bdat") - -@test sprint((stream,data)->show(stream, "text/html", data), ar) == "
vfloatvdoublevlongvintvbytevstring
3.143.142.02.02.0"2"
7.07.07.07.07.0"7"
#NA#NA#NA#NA#NA""
" -@test sprint((stream,data)->show(stream, "application/vnd.dataresource+json", data), ar) == -"{\"schema\":{\"fields\":[{\"name\":\"vfloat\",\"type\":\"number\"},{\"name\":\"vdouble\",\"type\":\"number\"},{\"name\":\"vlong\",\"type\":\"number\"},{\"name\":\"vint\",\"type\":\"number\"},{\"name\":\"vbyte\",\"type\":\"number\"},{\"name\":\"vstring\",\"type\":\"string\"}]},\"data\":[{\"vfloat\":3.140000104904175,\"vdouble\":3.14,\"vlong\":2.0,\"vint\":2.0,\"vbyte\":2.0,\"vstring\":\"2\"},{\"vfloat\":7.0,\"vdouble\":7.0,\"vlong\":7.0,\"vint\":7.0,\"vbyte\":7.0,\"vstring\":\"7\"},{\"vfloat\":null,\"vdouble\":null,\"vlong\":null,\"vint\":null,\"vbyte\":null,\"vstring\":\"\"}]}" -@test sprint(show, ar) == "3x6 SAS file\nvfloat │ vdouble │ vlong │ vint │ vbyte │ vstring\n───────┼─────────┼───────┼──────┼───────┼────────\n3.14 │ 3.14 │ 2.0 │ 2.0 │ 2.0 │ \"2\" \n7.0 │ 7.0 │ 7.0 │ 7.0 │ 7.0 │ \"7\" \n#NA │ #NA │ #NA │ #NA │ #NA │ \"\" " - -@test showable("text/html", ar) == true -@test showable("application/vnd.dataresource+json", ar) == true - -ar = load("types.sav") - -@test sprint((stream,data)->show(stream, "text/html", data), ar) == "
vfloatvdoublevlongvintvbytevstring
3.143.142.02.02.0"2"
7.07.07.07.07.0"7"
#NA#NA#NA#NA#NA""
" -@test sprint((stream,data)->show(stream, "application/vnd.dataresource+json", data), ar) == -"{\"schema\":{\"fields\":[{\"name\":\"vfloat\",\"type\":\"number\"},{\"name\":\"vdouble\",\"type\":\"number\"},{\"name\":\"vlong\",\"type\":\"number\"},{\"name\":\"vint\",\"type\":\"number\"},{\"name\":\"vbyte\",\"type\":\"number\"},{\"name\":\"vstring\",\"type\":\"string\"}]},\"data\":[{\"vfloat\":3.140000104904175,\"vdouble\":3.14,\"vlong\":2.0,\"vint\":2.0,\"vbyte\":2.0,\"vstring\":\"2\"},{\"vfloat\":7.0,\"vdouble\":7.0,\"vlong\":7.0,\"vint\":7.0,\"vbyte\":7.0,\"vstring\":\"7\"},{\"vfloat\":null,\"vdouble\":null,\"vlong\":null,\"vint\":null,\"vbyte\":null,\"vstring\":\"\"}]}" -@test sprint(show, ar) == "3x6 SPSS file\nvfloat │ vdouble │ vlong │ vint │ vbyte │ vstring\n───────┼─────────┼───────┼──────┼───────┼────────\n3.14 │ 3.14 │ 2.0 │ 2.0 │ 2.0 │ \"2\" \n7.0 │ 7.0 │ 7.0 │ 7.0 │ 7.0 │ \"7\" \n#NA │ #NA │ #NA │ #NA │ #NA │ \"\" " - -@test showable("text/html", ar) == true -@test showable("application/vnd.dataresource+json", ar) == true - -end +@run_package_tests diff --git a/test/test_statfiles.jl b/test/test_statfiles.jl new file mode 100644 index 0000000..7c26ab5 --- /dev/null +++ b/test/test_statfiles.jl @@ -0,0 +1,64 @@ +@testitem "StatFiles" begin + using IteratorInterfaceExtensions + using TableTraits + using DataValues + + ar = load(joinpath(@__DIR__, "types.dta")) |> IteratorInterfaceExtensions.getiterator |> collect + + @test length(ar) == 3 + @test ar[1] == (vfloat=DataValue{Float32}(3.14), vdouble=DataValue(3.14), vlong=DataValue{Int32}(2), vint=DataValue{Int16}(2), vbyte=DataValue{Int8}(2), vstring=DataValue("2")) + @test ar[2] == (vfloat=DataValue{Float32}(7.), vdouble=DataValue(7.), vlong=DataValue{Int32}(7), vint=DataValue{Int16}(7), vbyte=DataValue{Int8}(7), vstring=DataValue("7")) + @test ar[3] == (vfloat=DataValue{Float32}(), vdouble=DataValue{Float64}(), vlong=DataValue{Int32}(), vint=DataValue{Int16}(), vbyte=DataValue{Int8}(), vstring=DataValue("")) + @test TableTraits.isiterabletable(load(joinpath(@__DIR__, "types.dta"))) == true + @test IteratorInterfaceExtensions.isiterable(load(joinpath(@__DIR__, "types.dta"))) == true + + ar = load(joinpath(@__DIR__, "types.sas7bdat")) |> IteratorInterfaceExtensions.getiterator |> collect + + @test length(ar) == 3 + @test ar[1] == (vfloat=DataValue{Float32}(3.14), vdouble=DataValue(3.14), vlong=DataValue{Int32}(2), vint=DataValue{Int16}(2), vbyte=DataValue{Int8}(2), vstring=DataValue("2")) + @test ar[2] == (vfloat=DataValue{Float32}(7.), vdouble=DataValue(7.), vlong=DataValue{Int32}(7), vint=DataValue{Int16}(7), vbyte=DataValue{Int8}(7), vstring=DataValue("7")) + @test ar[3] == (vfloat=DataValue{Float32}(), vdouble=DataValue{Float64}(), vlong=DataValue{Int32}(), vint=DataValue{Int16}(), vbyte=DataValue{Int8}(), vstring=DataValue("")) + @test TableTraits.isiterabletable(load(joinpath(@__DIR__, "types.sas7bdat"))) == true + @test IteratorInterfaceExtensions.isiterable(load(joinpath(@__DIR__, "types.sas7bdat"))) == true + + ar = load(joinpath(@__DIR__, "types.sav")) |> IteratorInterfaceExtensions.getiterator |> collect + + @test length(ar) == 3 + @test ar[1] == (vfloat=DataValue{Float32}(3.14), vdouble=DataValue(3.14), vlong=DataValue{Int32}(2), vint=DataValue{Int16}(2), vbyte=DataValue{Int8}(2), vstring=DataValue("2")) + @test ar[2] == (vfloat=DataValue{Float32}(7.), vdouble=DataValue(7.), vlong=DataValue{Int32}(7), vint=DataValue{Int16}(7), vbyte=DataValue{Int8}(7), vstring=DataValue("7")) + @test ar[3] == (vfloat=DataValue{Float32}(), vdouble=DataValue{Float64}(), vlong=DataValue{Int32}(), vint=DataValue{Int16}(), vbyte=DataValue{Int8}(), vstring=DataValue("")) + @test TableTraits.isiterabletable(load(joinpath(@__DIR__, "types.sav"))) == true + @test IteratorInterfaceExtensions.isiterable(load(joinpath(@__DIR__, "types.sav"))) == true +end + +@testitem "Show" begin + ar = load(joinpath(@__DIR__, "types.dta")) + + @test sprint((stream,data)->show(stream, "text/html", data), ar) == "
vfloatvdoublevlongvintvbytevstring
3.143.14222"2"
7.07.0777"7"
#NA#NA#NA#NA#NA""
" + @test sprint((stream,data)->show(stream, "application/vnd.dataresource+json", data), ar) == + "{\"schema\":{\"fields\":[{\"name\":\"vfloat\",\"type\":\"number\"},{\"name\":\"vdouble\",\"type\":\"number\"},{\"name\":\"vlong\",\"type\":\"integer\"},{\"name\":\"vint\",\"type\":\"integer\"},{\"name\":\"vbyte\",\"type\":\"integer\"},{\"name\":\"vstring\",\"type\":\"string\"}]},\"data\":[{\"vfloat\":3.14,\"vdouble\":3.14,\"vlong\":2,\"vint\":2,\"vbyte\":2,\"vstring\":\"2\"},{\"vfloat\":7.0,\"vdouble\":7.0,\"vlong\":7,\"vint\":7,\"vbyte\":7,\"vstring\":\"7\"},{\"vfloat\":null,\"vdouble\":null,\"vlong\":null,\"vint\":null,\"vbyte\":null,\"vstring\":\"\"}]}" + @test sprint(show, ar) == "3x6 STATA file\nvfloat │ vdouble │ vlong │ vint │ vbyte │ vstring\n───────┼─────────┼───────┼──────┼───────┼────────\n3.14 │ 3.14 │ 2 │ 2 │ 2 │ \"2\" \n7.0 │ 7.0 │ 7 │ 7 │ 7 │ \"7\" \n#NA │ #NA │ #NA │ #NA │ #NA │ \"\" " + + @test showable("text/html", ar) == true + @test showable("application/vnd.dataresource+json", ar) == true + + ar = load(joinpath(@__DIR__, "types.sas7bdat")) + + @test sprint((stream,data)->show(stream, "text/html", data), ar) == "
vfloatvdoublevlongvintvbytevstring
3.143.142.02.02.0"2"
7.07.07.07.07.0"7"
#NA#NA#NA#NA#NA""
" + @test sprint((stream,data)->show(stream, "application/vnd.dataresource+json", data), ar) == + "{\"schema\":{\"fields\":[{\"name\":\"vfloat\",\"type\":\"number\"},{\"name\":\"vdouble\",\"type\":\"number\"},{\"name\":\"vlong\",\"type\":\"number\"},{\"name\":\"vint\",\"type\":\"number\"},{\"name\":\"vbyte\",\"type\":\"number\"},{\"name\":\"vstring\",\"type\":\"string\"}]},\"data\":[{\"vfloat\":3.140000104904175,\"vdouble\":3.14,\"vlong\":2.0,\"vint\":2.0,\"vbyte\":2.0,\"vstring\":\"2\"},{\"vfloat\":7.0,\"vdouble\":7.0,\"vlong\":7.0,\"vint\":7.0,\"vbyte\":7.0,\"vstring\":\"7\"},{\"vfloat\":null,\"vdouble\":null,\"vlong\":null,\"vint\":null,\"vbyte\":null,\"vstring\":\"\"}]}" + @test sprint(show, ar) == "3x6 SAS file\nvfloat │ vdouble │ vlong │ vint │ vbyte │ vstring\n───────┼─────────┼───────┼──────┼───────┼────────\n3.14 │ 3.14 │ 2.0 │ 2.0 │ 2.0 │ \"2\" \n7.0 │ 7.0 │ 7.0 │ 7.0 │ 7.0 │ \"7\" \n#NA │ #NA │ #NA │ #NA │ #NA │ \"\" " + + @test showable("text/html", ar) == true + @test showable("application/vnd.dataresource+json", ar) == true + + ar = load(joinpath(@__DIR__, "types.sav")) + + @test sprint((stream,data)->show(stream, "text/html", data), ar) == "
vfloatvdoublevlongvintvbytevstring
3.143.142.02.02.0"2"
7.07.07.07.07.0"7"
#NA#NA#NA#NA#NA""
" + @test sprint((stream,data)->show(stream, "application/vnd.dataresource+json", data), ar) == + "{\"schema\":{\"fields\":[{\"name\":\"vfloat\",\"type\":\"number\"},{\"name\":\"vdouble\",\"type\":\"number\"},{\"name\":\"vlong\",\"type\":\"number\"},{\"name\":\"vint\",\"type\":\"number\"},{\"name\":\"vbyte\",\"type\":\"number\"},{\"name\":\"vstring\",\"type\":\"string\"}]},\"data\":[{\"vfloat\":3.140000104904175,\"vdouble\":3.14,\"vlong\":2.0,\"vint\":2.0,\"vbyte\":2.0,\"vstring\":\"2\"},{\"vfloat\":7.0,\"vdouble\":7.0,\"vlong\":7.0,\"vint\":7.0,\"vbyte\":7.0,\"vstring\":\"7\"},{\"vfloat\":null,\"vdouble\":null,\"vlong\":null,\"vint\":null,\"vbyte\":null,\"vstring\":\"\"}]}" + @test sprint(show, ar) == "3x6 SPSS file\nvfloat │ vdouble │ vlong │ vint │ vbyte │ vstring\n───────┼─────────┼───────┼──────┼───────┼────────\n3.14 │ 3.14 │ 2.0 │ 2.0 │ 2.0 │ \"2\" \n7.0 │ 7.0 │ 7.0 │ 7.0 │ 7.0 │ \"7\" \n#NA │ #NA │ #NA │ #NA │ #NA │ \"\" " + + @test showable("text/html", ar) == true + @test showable("application/vnd.dataresource+json", ar) == true +end From 33f999235cd5c0479f1faecd2cfe8eee3c21b401 Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Fri, 28 Aug 2026 18:21:05 -0700 Subject: [PATCH 2/4] Bump version to 1.0.0-DEV Move the package off 0.x to a proper 1.0 major version, and accept 1.0 versions of Queryverse sibling packages in compat. Co-Authored-By: Claude Fable 5 --- Project.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index bc43f02..6848626 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "StatFiles" uuid = "1463e38c-9381-5320-bcd4-4134955f093a" -version = "0.9.0-DEV" +version = "1.0.0-DEV" [deps] DataValues = "e7dc6d0d-1eca-5fa6-8ad6-5aecde8b7ea5" @@ -20,12 +20,12 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" test = ["Test", "TestItemRunner"] [compat] -DataValues = "0.4.4, 0.5" +DataValues = "0.4.4, 0.5, 1" FileIO = "1" IterableTables = "0.8.3, 0.9, 0.10, 0.11, 1" IteratorInterfaceExtensions = "0.1.1, 1" ReadStat = "0.4.1, 1" -TableShowUtils = "0.1.1, 0.2, 0.3" +TableShowUtils = "0.1.1, 0.2, 0.3, 1" TableTraits = "0.3.1, 0.4, 1" TableTraitsUtils = "0.2.1, 0.3, 0.4, 1" julia = "1.12" From 4ef05b282e300d0769edb0a61d102b2b9da2f042 Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Fri, 28 Aug 2026 21:02:06 -0700 Subject: [PATCH 3/4] Restore original Julia compat range Keep supporting the Julia versions the package supported before the test item migration instead of raising the floor to 1.12. Co-Authored-By: Claude Fable 5 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 6848626..b641932 100644 --- a/Project.toml +++ b/Project.toml @@ -28,4 +28,4 @@ ReadStat = "0.4.1, 1" TableShowUtils = "0.1.1, 0.2, 0.3, 1" TableTraits = "0.3.1, 0.4, 1" TableTraitsUtils = "0.2.1, 0.3, 0.4, 1" -julia = "1.12" +julia = "1" From fb42070f2b0f3a3456af8ec170014a2b83be9e33 Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Sat, 29 Aug 2026 01:07:11 -0700 Subject: [PATCH 4/4] Set Julia floor to 1.3 to match ReadStat On Julia 1.0-1.2 the resolver picks the BinaryProvider-era ReadStat whose binaries can no longer be built, so those CI legs cannot pass. ReadStat.jl itself requires Julia 1.3; align StatFiles with it. Co-Authored-By: Claude Fable 5 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index b641932..2227c02 100644 --- a/Project.toml +++ b/Project.toml @@ -28,4 +28,4 @@ ReadStat = "0.4.1, 1" TableShowUtils = "0.1.1, 0.2, 0.3, 1" TableTraits = "0.3.1, 0.4, 1" TableTraitsUtils = "0.2.1, 0.3, 0.4, 1" -julia = "1" +julia = "1.3"