From 900e4179695b465753aa1711c715d9d8ff981c9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller-Widmann?= Date: Tue, 20 Oct 2026 13:26:05 +0200 Subject: [PATCH 1/4] Fix typos Fix misspellings in README, docstrings, comments and tests found by typos, plus two it misses ("based ion", "a arbitrary"). Co-Authored-By: Claude Opus 5.5 --- README.md | 6 +++--- src/check_result.jl | 4 ++-- src/generate_tangent.jl | 2 +- src/global_config.jl | 2 +- src/output_control.jl | 6 +++--- src/rand_tangent.jl | 4 ++-- src/testers.jl | 2 +- test/check_result.jl | 2 +- test/rand_tangent.jl | 2 +- test/testers.jl | 2 +- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 38e27b21..4c474cb1 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ [![](https://img.shields.io/badge/docs-stable-blue.svg)](https://JuliaDiff.github.io/ChainRulesTestUtils.jl/stable) -| ⚠️ The ChainRules project is currently seeking a new primary maintainer ⚠️ | -|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| See this [Discourse thread](https://discourse.julialang.org/t/chainrules-project-looking-for-a-new-primary-maintainer/115636). We currently have many secondary maintainers and contributors with commit rights, but noone who has committed to leading the efforts. Until this is resolved PRs and issues may not recieve timely response. | +| ⚠️ The ChainRules project is currently seeking a new primary maintainer ⚠️ | +|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| See this [Discourse thread](https://discourse.julialang.org/t/chainrules-project-looking-for-a-new-primary-maintainer/115636). We currently have many secondary maintainers and contributors with commit rights, but no one who has committed to leading the efforts. Until this is resolved PRs and issues may not receive timely response. | > Collection of utilities for testing forward- and reverse-mode AD sensitivities. diff --git a/src/check_result.jl b/src/check_result.jl index 0f192a47..2002eee6 100644 --- a/src/check_result.jl +++ b/src/check_result.jl @@ -120,12 +120,12 @@ function test_approx( @test ActualPrimal === ExpectedPrimal end -# Some structual differential and a natural differential +# Some structural differential and a natural differential function test_approx(actual::Tangent{P,T}, expected, msg=""; kwargs...) where {T,P} if _can_pass_early(actual, expected) @test true else - @assert (T <: NamedTuple) # it should be a structual differential if we hit this + @assert (T <: NamedTuple) # it should be a structural differential if we hit this # We are only checking the properties that are in the Tangent # the natural differential is allowed to have other properties that we ignore diff --git a/src/generate_tangent.jl b/src/generate_tangent.jl index c76dcfec..cf935107 100644 --- a/src/generate_tangent.jl +++ b/src/generate_tangent.jl @@ -32,7 +32,7 @@ const ⊢ = PrimalAndTangent auto_primal_and_tangent(primal; rng=Random.GLOBAL_RNG) auto_primal_and_tangent(::PrimalAndTangent; rng=Random.GLOBAL_RNG) -Convience constructor for `PrimalAndTangent` where the primal is provided +Convenience constructor for `PrimalAndTangent` where the primal is provided This function is idempotent. If you pass it a `PrimalAndTangent` it doesn't change it. """ diff --git a/src/global_config.jl b/src/global_config.jl index 9e330337..6a41bc25 100644 --- a/src/global_config.jl +++ b/src/global_config.jl @@ -2,7 +2,7 @@ const _fdm = central_fdm(5, 1; max_range=1e-2) const TEST_INFERRED = Ref(true) const TRANSFORMS_TO_ALT_TANGENTS = Function[x->@thunk(x)] # e.g. [_ -> ZeroTangent(), x -> rebasis(x)] -"sets up TEST_INFERRED based ion enviroment variables" +"sets up TEST_INFERRED based on environment variables" function init_test_inferred_setting!() TEST_INFERRED[] = if haskey(ENV, "CHAINRULES_TEST_INFERRED") parse(Bool, "CHAINRULES_TEST_INFERRED") diff --git a/src/output_control.jl b/src/output_control.jl index c1eb5b3f..12d9a9f1 100644 --- a/src/output_control.jl +++ b/src/output_control.jl @@ -14,12 +14,12 @@ struct ExprAndMsg end """ - @test_msg msg condion kws... + @test_msg msg condition kws... -This is per `Test.@test condion kws...` except that if it fails it also prints the `msg`. +This is per `Test.@test condition kws...` except that if it fails it also prints the `msg`. If `msg==""` then this is just like `@test`, nothing is printed -### Examles +### Examples ```julia julia> @test_msg "It is required that the total is under 10" sum(1:1000) < 10; Test Failed at REPL[1]:1 diff --git a/src/rand_tangent.jl b/src/rand_tangent.jl index fbc60cac..216003a8 100644 --- a/src/rand_tangent.jl +++ b/src/rand_tangent.jl @@ -1,9 +1,9 @@ """ rand_tangent([rng::AbstractRNG,] x) -Returns a arbitary tangent vector _appropriate_ for the primal value `x`. +Returns an arbitrary tangent vector _appropriate_ for the primal value `x`. Note that despite the name, no promises on the statistical randomness are made. -Rather it is an arbitary value, that is generated using the `rng`. +Rather it is an arbitrary value, that is generated using the `rng`. """ rand_tangent(x) = rand_tangent(Random.GLOBAL_RNG, x) diff --git a/src/testers.jl b/src/testers.jl index 67dbbf3e..28c859c7 100644 --- a/src/testers.jl +++ b/src/testers.jl @@ -291,7 +291,7 @@ approximately equal to the cotangent `fd_cotangent` obtained with finite differe If `accum_cotangent` is `NoTangent()`, i.e., the argument was marked as non-differentiable, `ad_cotangent` and `fd_cotangent` should be `NoTangent()` as well. -If a msg string is given, it is emmited on test failure. +If a msg string is given, it is emitted on test failure. # Keyword arguments - If `check_inferred=true` (the default) and `ad_cotangent` is a thunk, then it is checked if diff --git a/test/check_result.jl b/test/check_result.jl index d50dcbc1..d63fc0e6 100644 --- a/test/check_result.jl +++ b/test/check_result.jl @@ -54,7 +54,7 @@ end ) diag_eg = Diagonal(randn(5)) - test_approx( # Structual == Structural + test_approx( # Structural == Structural Tangent{typeof(diag_eg)}(; diag=diag_eg.diag), Tangent{typeof(diag_eg)}(; diag=diag_eg.diag), ) diff --git a/test/rand_tangent.jl b/test/rand_tangent.jl index 485f4384..4e76e3b4 100644 --- a/test/rand_tangent.jl +++ b/test/rand_tangent.jl @@ -46,7 +46,7 @@ struct Bar (transpose(randn(5)), Transpose{Float64, Vector{Float64}}), # row-vector: special (transpose(randn(5, 4)), Matrix{Float64}), # matrix: generic dense - # AbstactArrays of non-perturbable types + # AbstractArrays of non-perturbable types (1:10, NoTangent), (1:2:10, NoTangent), ([false, true], NoTangent), diff --git a/test/testers.jl b/test/testers.jl index 999bdcf3..591eab2b 100644 --- a/test/testers.jl +++ b/test/testers.jl @@ -442,7 +442,7 @@ end return x, ẋ end - # these pass in tangents explictly so that we can check them after + # these pass in tangents explicitly so that we can check them after x = randn(3) ẋ = [4.0, 5.0, 6.0] xcopy, ẋcopy = copy(x), copy(ẋ) From a0c3cbe1abc75fb4717004ed79ab50b11db9e23a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller-Widmann?= Date: Tue, 20 Oct 2026 13:35:01 +0200 Subject: [PATCH 2/4] Modernize CI setup Bring the CI setup in line with ChainRulesCore (JuliaDiff/ChainRulesCore.jl#715) and ChainRules (JuliaDiff/ChainRules.jl#850): - Replace CompatHelper with Dependabot's `julia` ecosystem - Add a `typos` spell check workflow - Test `pre` on Linux with allowed failures instead of a separate JuliaNightly workflow, and upload coverage from the CI jobs - Build the docs in the CI workflow on Julia 1; the separate Documenter workflow only ran on pushes to the non-existent `master` branch - Run IntegrationTest on `main`, add cache and permissions, and test downstream packages in a temporary environment - Add concurrency and permissions everywhere and update action versions (no more `@latest`) Co-Authored-By: Claude Opus 5.5 --- .github/dependabot.yml | 8 ++++ .github/workflows/CI.yml | 54 ++++++++++++++++++++++++--- .github/workflows/CompatHelper.yml | 17 --------- .github/workflows/Documenter.yml | 20 ---------- .github/workflows/IntegrationTest.yml | 42 +++++++++++++-------- .github/workflows/JuliaNightly.yml | 28 -------------- .github/workflows/SpellCheck.yml | 23 ++++++++++++ .github/workflows/fix_doctests.yml | 21 ++++++++--- 8 files changed, 121 insertions(+), 92 deletions(-) delete mode 100644 .github/workflows/CompatHelper.yml delete mode 100644 .github/workflows/Documenter.yml delete mode 100644 .github/workflows/JuliaNightly.yml create mode 100644 .github/workflows/SpellCheck.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 700707ce..2bd27c77 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,3 +5,11 @@ updates: directory: "/" # Location of package manifests schedule: interval: "weekly" + - package-ecosystem: "julia" + directory: "/" + schedule: + interval: "weekly" + groups: + all-julia-packages: + patterns: + - "*" diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index c1c752d6..6251f533 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -5,25 +5,67 @@ on: tags: [v*] pull_request: +concurrency: + # Skip intermediate builds: always. + # Cancel intermediate builds: only if it is a pull request build. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} + +# needed to allow julia-actions/cache to delete old caches that it has created +permissions: + actions: write + contents: read + jobs: test: - name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} + name: Julia ${{ matrix.version }} - ${{ matrix.os }} runs-on: ${{ matrix.os }} + continue-on-error: ${{ matrix.allow-failure == true }} strategy: fail-fast: false matrix: version: - - "lts" - - "1" # Latest Release + - "lts" # Long-term support version + - "1" # Latest Release os: - ubuntu-latest - macOS-latest # Apple silicon - windows-latest + include: + - os: ubuntu-latest + version: "pre" + allow-failure: true steps: - - uses: actions/checkout@v4 - - uses: julia-actions/setup-julia@v2 + - uses: actions/checkout@v7 + - uses: julia-actions/setup-julia@v3 with: version: ${{ matrix.version }} - - uses: julia-actions/cache@v2 + - uses: julia-actions/cache@v3 - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 + - uses: julia-actions/julia-processcoverage@v1 + - uses: codecov/codecov-action@v7 + with: + files: lcov.info + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: true + + docs: + name: Documentation + runs-on: ubuntu-latest + permissions: + actions: write + contents: write # Required when authenticating with `GITHUB_TOKEN`, not needed when authenticating with SSH deploy keys + pull-requests: read # Required when using `push_preview=true` + statuses: write # Optional, used to report documentation build statuses + steps: + - uses: actions/checkout@v7 + - uses: julia-actions/setup-julia@v3 + with: + version: '1' + - uses: julia-actions/cache@v3 + - run: julia --project=docs -e 'using Pkg; Pkg.instantiate()' + - run: julia --project=docs docs/make.jl + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} diff --git a/.github/workflows/CompatHelper.yml b/.github/workflows/CompatHelper.yml deleted file mode 100644 index 226f6040..00000000 --- a/.github/workflows/CompatHelper.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: CompatHelper - -on: - schedule: - - cron: '00 00 * * *' - -jobs: - CompatHelper: - 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 }} - COMPATHELPER_PRIV: ${{ secrets.DOCUMENTER_KEY }} - run: julia -e 'using CompatHelper; CompatHelper.main()' diff --git a/.github/workflows/Documenter.yml b/.github/workflows/Documenter.yml deleted file mode 100644 index e2a15d5e..00000000 --- a/.github/workflows/Documenter.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Documenter -on: - push: - branches: [master] - tags: [v*] - pull_request: - -jobs: - docs: - name: Documentation - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: julia-actions/setup-julia@v2 - with: - version: '1.10' - - uses: julia-actions/julia-docdeploy@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} diff --git a/.github/workflows/IntegrationTest.yml b/.github/workflows/IntegrationTest.yml index a0dca430..ffe18c4d 100644 --- a/.github/workflows/IntegrationTest.yml +++ b/.github/workflows/IntegrationTest.yml @@ -1,13 +1,24 @@ name: IntegrationTest on: push: - branches: [master] + branches: [main] tags: [v*] pull_request: +concurrency: + # Skip intermediate builds: always. + # Cancel intermediate builds: only if it is a pull request build. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} + +# needed to allow julia-actions/cache to delete old caches that it has created +permissions: + actions: write + contents: read + jobs: test: - name: ${{ matrix.package.repo }} + name: ${{ matrix.package.name }} runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -15,30 +26,31 @@ jobs: julia-version: [1] os: [ubuntu-latest] package: - - {user: JuliaDiff, repo: ChainRules.jl} - - {user: JuliaMath, repo: SpecialFunctions.jl} - - {user: invenia, repo: BlockDiagonals.jl} + - {user: JuliaDiff, name: ChainRules} + - {user: JuliaMath, name: SpecialFunctions} + - {user: invenia, name: BlockDiagonals} + steps: - - uses: actions/checkout@v2 - - uses: julia-actions/setup-julia@v1 + - uses: actions/checkout@v7 + - uses: julia-actions/setup-julia@v3 with: version: ${{ matrix.julia-version }} - arch: x64 - - uses: julia-actions/julia-buildpkg@latest + - uses: julia-actions/cache@v3 + - uses: julia-actions/julia-buildpkg@v1 - name: Clone Downstream - uses: actions/checkout@v2 + uses: actions/checkout@v7 with: - repository: ${{ matrix.package.user }}/${{ matrix.package.repo }} + repository: ${{ matrix.package.user }}/${{ matrix.package.name }}.jl path: downstream - name: Load this and run the downstream tests - shell: julia --project=downstream {0} + shell: julia --project=@temp {0} run: | using Pkg try # force it to use this PR's version of the package - Pkg.develop(PackageSpec(path=".")) # resolver may fail with main deps + Pkg.develop([PackageSpec(path="."), PackageSpec(path="downstream")]) # resolver may fail with main deps Pkg.update() - Pkg.test() # resolver may fail with test time deps + Pkg.test("${{ matrix.package.name }}") # resolver may fail with test time deps catch err err isa Pkg.Resolve.ResolverError || rethrow() # If we can't resolve that means this is incompatible by SemVer and this is fine @@ -46,5 +58,5 @@ jobs: # Mistakenly introducing a breaking change, as we have intentionally made one @info "Not compatible with this release. No problem." exception=err - exit(0) # Exit immediately, as a success + exit(0) # Exit immediately, as a success end diff --git a/.github/workflows/JuliaNightly.yml b/.github/workflows/JuliaNightly.yml deleted file mode 100644 index d380a669..00000000 --- a/.github/workflows/JuliaNightly.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: JuliaNightly -# Nightly Version of Julia. -# Runs on PRs and pushes to `master`, but seperate workflow to `CI` -# to avoid inclusion in nightly cron build with failure notifications. -on: - push: - branches: [master] - tags: ["*"] - pull_request: - -jobs: - test: - name: Julia Nightly - Ubuntu - x64 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: julia-actions/setup-julia@v2 - with: - version: nightly - - uses: julia-actions/cache@v2 - - uses: julia-actions/julia-buildpkg@v1 - - uses: julia-actions/julia-runtest@v1 - - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v5 - continue-on-error: true - with: - token: ${{ secrets.CODECOV_TOKEN }} # required - file: lcov.info diff --git a/.github/workflows/SpellCheck.yml b/.github/workflows/SpellCheck.yml new file mode 100644 index 00000000..99782e94 --- /dev/null +++ b/.github/workflows/SpellCheck.yml @@ -0,0 +1,23 @@ +name: Spell Check + +on: + push: + branches: [main] + pull_request: + +concurrency: + # Skip intermediate builds: always. + # Cancel intermediate builds: only if it is a pull request build. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} + +permissions: + contents: read + +jobs: + typos: + name: Spell Check with Typos + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: crate-ci/typos@v1.51.1 diff --git a/.github/workflows/fix_doctests.yml b/.github/workflows/fix_doctests.yml index 05040a13..ccb5f3cd 100644 --- a/.github/workflows/fix_doctests.yml +++ b/.github/workflows/fix_doctests.yml @@ -1,6 +1,17 @@ name: fix_doctests on: pull_request: + +concurrency: + # Skip intermediate builds: always. + # Cancel intermediate builds: always. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: write # Required by reviewdog/action-suggester to post suggestions + jobs: doctests: name: Fix doctests (Julia ${{ matrix.julia-version }} - ${{ github.event_name }}) @@ -8,21 +19,19 @@ jobs: strategy: matrix: julia-version: - - '1.10' + - '1' steps: - - uses: actions/checkout@v4 - - uses: julia-actions/setup-julia@latest + - uses: actions/checkout@v7 + - uses: julia-actions/setup-julia@v3 with: version: ${{ matrix.julia-version }} - name: Fix doctests shell: julia --project=docs/ {0} run: | - using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate() + using Pkg; Pkg.instantiate() using Documenter using ChainRulesTestUtils doctest(ChainRulesTestUtils, fix=true) - # don't push changes to Manifest in suggestions, as it removes `path=..` - run(`git restore docs/Manifest.toml`) - uses: reviewdog/action-suggester@v1 if: github.event_name == 'pull_request' with: From dfa4d83dee709601f773fc4ad9d1ac25b468a25c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller-Widmann?= Date: Tue, 20 Oct 2026 14:29:00 +0200 Subject: [PATCH 3/4] Modernize Julia setup Bring the package setup in line with ChainRulesCore (JuliaDiff/ChainRulesCore.jl#717): - Require Julia 1.10 (the current LTS) and drop the obsolete version checks in the tests - Remove the Compat dependency (`only` is in Base since Julia 1.4) - Add compat entries for the stdlibs - Move the test dependencies to test/Project.toml and make the test and docs environments part of a workspace, using [sources] instead of `Pkg.develop` and a checked-in docs/Manifest.toml - Update Documenter to v1 and fix the doctests, which were silently failing with Documenter 0.27: ignore `Test Summary` tables (they differ between `makedocs` and `doctest` and across Julia versions) and don't run the deliberately failing `test_rrule` example, whose output is random - Set `devbranch = "main"` in `deploydocs` Co-Authored-By: Claude Opus 5.5 --- .gitignore | 2 +- Project.toml | 17 ++- docs/Manifest.toml | 212 ------------------------------------- docs/Project.toml | 8 +- docs/make.jl | 2 +- docs/src/index.md | 11 +- src/ChainRulesTestUtils.jl | 1 - test/Project.toml | 19 ++++ test/global_checks.jl | 44 ++++---- test/rand_tangent.jl | 3 +- 10 files changed, 61 insertions(+), 258 deletions(-) delete mode 100644 docs/Manifest.toml create mode 100644 test/Project.toml diff --git a/.gitignore b/.gitignore index ff6ef274..a6a593be 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,7 @@ docs/site/ # It records a fixed state of all packages used by the project. As such, it should not be # committed for packages, but should be committed for applications that require a static # environment. -/Manifest.toml +Manifest*.toml # JetBrains meta files .idea/* diff --git a/Project.toml b/Project.toml index 7b39331c..4a0ba9af 100644 --- a/Project.toml +++ b/Project.toml @@ -1,10 +1,9 @@ name = "ChainRulesTestUtils" uuid = "cdddcdb0-9152-4a09-a978-84456f9df70a" -version = "1.13.1" +version = "1.13.2" [deps] ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" -Compat = "34da2185-b29b-5c13-b0c7-acf172513d20" FiniteDifferences = "26cc04aa-876d-5657-8c51-4c34ba976000" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" @@ -13,14 +12,12 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [compat] ChainRulesCore = "1.11.2" -Compat = "3, 4" FiniteDifferences = "0.12.12" -MetaTesting = "0.1" +LinearAlgebra = "1" +Random = "1" Suppressor = "0.2.6" -julia = "1" +Test = "1" +julia = "1.10" -[extras] -MetaTesting = "9e32d19f-1e4f-477a-8631-b16c78aa0f56" - -[targets] -test = ["MetaTesting"] +[workspace] +projects = ["test", "docs"] diff --git a/docs/Manifest.toml b/docs/Manifest.toml deleted file mode 100644 index ab985dcb..00000000 --- a/docs/Manifest.toml +++ /dev/null @@ -1,212 +0,0 @@ -# This file is machine-generated - editing it directly is not advised - -[[ANSIColoredPrinters]] -git-tree-sha1 = "574baf8110975760d391c710b6341da1afa48d8c" -uuid = "a4c015fc-c6ff-483c-b24f-f7ea428134e9" -version = "0.0.1" - -[[ArgTools]] -uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" - -[[Artifacts]] -uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" - -[[Base64]] -uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" - -[[ChainRulesCore]] -deps = ["Compat", "LinearAlgebra", "SparseArrays"] -git-tree-sha1 = "f885e7e7c124f8c92650d61b9477b9ac2ee607dd" -uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" -version = "1.11.1" - -[[ChainRulesTestUtils]] -deps = ["ChainRulesCore", "Compat", "FiniteDifferences", "LinearAlgebra", "Random", "Test"] -path = ".." -uuid = "cdddcdb0-9152-4a09-a978-84456f9df70a" -version = "1.2.4" - -[[Compat]] -deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"] -git-tree-sha1 = "dce3e3fea680869eaa0b774b2e8343e9ff442313" -uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "3.40.0" - -[[Dates]] -deps = ["Printf"] -uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" - -[[DelimitedFiles]] -deps = ["Mmap"] -uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab" - -[[Distributed]] -deps = ["Random", "Serialization", "Sockets"] -uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" - -[[DocStringExtensions]] -deps = ["LibGit2"] -git-tree-sha1 = "b19534d1895d702889b219c382a6e18010797f0b" -uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" -version = "0.8.6" - -[[Documenter]] -deps = ["ANSIColoredPrinters", "Base64", "Dates", "DocStringExtensions", "IOCapture", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "REPL", "Test", "Unicode"] -git-tree-sha1 = "f425293f7e0acaf9144de6d731772de156676233" -uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -version = "0.27.10" - -[[Downloads]] -deps = ["ArgTools", "LibCURL", "NetworkOptions"] -uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" - -[[FiniteDifferences]] -deps = ["ChainRulesCore", "LinearAlgebra", "Printf", "Random", "Richardson", "StaticArrays"] -git-tree-sha1 = "c56a261e1a5472f20cbd7aa218840fd203243319" -uuid = "26cc04aa-876d-5657-8c51-4c34ba976000" -version = "0.12.19" - -[[IOCapture]] -deps = ["Logging", "Random"] -git-tree-sha1 = "f7be53659ab06ddc986428d3a9dcc95f6fa6705a" -uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89" -version = "0.2.2" - -[[InteractiveUtils]] -deps = ["Markdown"] -uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" - -[[JSON]] -deps = ["Dates", "Mmap", "Parsers", "Unicode"] -git-tree-sha1 = "8076680b162ada2a031f707ac7b4953e30667a37" -uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" -version = "0.21.2" - -[[LibCURL]] -deps = ["LibCURL_jll", "MozillaCACerts_jll"] -uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" - -[[LibCURL_jll]] -deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] -uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" - -[[LibGit2]] -deps = ["Base64", "NetworkOptions", "Printf", "SHA"] -uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" - -[[LibSSH2_jll]] -deps = ["Artifacts", "Libdl", "MbedTLS_jll"] -uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" - -[[Libdl]] -uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" - -[[LinearAlgebra]] -deps = ["Libdl"] -uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" - -[[Logging]] -uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" - -[[Markdown]] -deps = ["Base64"] -uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" - -[[MbedTLS_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" - -[[Mmap]] -uuid = "a63ad114-7e13-5084-954f-fe012c677804" - -[[MozillaCACerts_jll]] -uuid = "14a3606d-f60d-562e-9121-12d972cd8159" - -[[NetworkOptions]] -uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" - -[[Parsers]] -deps = ["Dates"] -git-tree-sha1 = "ae4bbcadb2906ccc085cf52ac286dc1377dceccc" -uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" -version = "2.1.2" - -[[Pkg]] -deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] -uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" - -[[Printf]] -deps = ["Unicode"] -uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" - -[[REPL]] -deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] -uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" - -[[Random]] -deps = ["Serialization"] -uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" - -[[Richardson]] -deps = ["LinearAlgebra"] -git-tree-sha1 = "e03ca566bec93f8a3aeb059c8ef102f268a38949" -uuid = "708f8203-808e-40c0-ba2d-98a6953ed40d" -version = "1.4.0" - -[[SHA]] -uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" - -[[Serialization]] -uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" - -[[SharedArrays]] -deps = ["Distributed", "Mmap", "Random", "Serialization"] -uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" - -[[Sockets]] -uuid = "6462fe0b-24de-5631-8697-dd941f90decc" - -[[SparseArrays]] -deps = ["LinearAlgebra", "Random"] -uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" - -[[StaticArrays]] -deps = ["LinearAlgebra", "Random", "Statistics"] -git-tree-sha1 = "3c76dde64d03699e074ac02eb2e8ba8254d428da" -uuid = "90137ffa-7385-5640-81b9-e52037218182" -version = "1.2.13" - -[[Statistics]] -deps = ["LinearAlgebra", "SparseArrays"] -uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" - -[[TOML]] -deps = ["Dates"] -uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" - -[[Tar]] -deps = ["ArgTools", "SHA"] -uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" - -[[Test]] -deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] -uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - -[[UUIDs]] -deps = ["Random", "SHA"] -uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" - -[[Unicode]] -uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" - -[[Zlib_jll]] -deps = ["Libdl"] -uuid = "83775a58-1f1d-513f-b197-d71354ab007a" - -[[nghttp2_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" - -[[p7zip_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" diff --git a/docs/Project.toml b/docs/Project.toml index 48d5ec85..7efe21ee 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -4,5 +4,9 @@ ChainRulesTestUtils = "cdddcdb0-9152-4a09-a978-84456f9df70a" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" [compat] -Documenter = "0.27" -julia = "1" +ChainRulesCore = "1" +ChainRulesTestUtils = "1" +Documenter = "1" + +[sources] +ChainRulesTestUtils = { path = ".." } diff --git a/docs/make.jl b/docs/make.jl index 0bc71525..0f86738e 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -15,4 +15,4 @@ makedocs(; ) const repo = "github.com/JuliaDiff/ChainRulesTestUtils.jl.git" -deploydocs(; repo=repo, push_preview=true) +deploydocs(; repo=repo, devbranch="main", push_preview=true) diff --git a/docs/src/index.md b/docs/src/index.md index 77f6c8e9..7a3dc469 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,5 +1,8 @@ ```@meta -DocTestFilters = [r"[0-9\.]+s",r"isapprox\(.*\)"] +# `Test Summary` tables depend on the Julia version and on whether the doctests +# run in `makedocs` or in `doctest`, so we do not compare them. The group is optional +# since Documenter only applies filters that match both the expected and actual output. +DocTestFilters = [r"(Test Summary:[^\n]*\n[^\n]*\|[^\n]*)?"] ``` # ChainRulesTestUtils @@ -78,7 +81,7 @@ test_frule: two2three on Float64,Float64 | 6 6 2.7s [`test_rrule`](@ref) takes in the function `f`, and primal inputs `x`. The call will test the `rrule` for function `f` at the point `x`, and similarly to `frule` some rules should be tested at multiple points in the domain. -```jldoctest ex +```julia julia> test_rrule(two2three, 3.33, -7.77); test_rrule: two2three on Float64,Float64: Test Failed at /home/lior/.julia/dev/ChainRulesTestUtils/src/check_result.jl:24 Expression: isapprox(actual, expected; kwargs...) @@ -114,12 +117,12 @@ call. ```jldoctest ex julia> test_scalar(relu, 0.5); Test Summary: | Pass Total Time -test_scalar: relu at 0.5 | 12 12 1.2s +test_scalar: relu at 0.5 | 11 11 1.2s julia> test_scalar(relu, -0.5); Test Summary: | Pass Total Time -test_scalar: relu at -0.5 | 12 12 0.0s +test_scalar: relu at -0.5 | 11 11 0.0s ``` diff --git a/src/ChainRulesTestUtils.jl b/src/ChainRulesTestUtils.jl index 2d424f1c..5195dd0e 100644 --- a/src/ChainRulesTestUtils.jl +++ b/src/ChainRulesTestUtils.jl @@ -4,7 +4,6 @@ module ChainRulesTestUtils using ChainRulesCore using ChainRulesCore: frule, rrule -using Compat: only using FiniteDifferences using FiniteDifferences: to_vec using LinearAlgebra diff --git a/test/Project.toml b/test/Project.toml new file mode 100644 index 00000000..eaebaf93 --- /dev/null +++ b/test/Project.toml @@ -0,0 +1,19 @@ +[deps] +ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" +ChainRulesTestUtils = "cdddcdb0-9152-4a09-a978-84456f9df70a" +FiniteDifferences = "26cc04aa-876d-5657-8c51-4c34ba976000" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +MetaTesting = "9e32d19f-1e4f-477a-8631-b16c78aa0f56" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[compat] +ChainRulesCore = "1" +FiniteDifferences = "0.12.12" +LinearAlgebra = "1" +MetaTesting = "0.1" +Random = "1" +Test = "1" + +[sources] +ChainRulesTestUtils = { path = ".." } diff --git a/test/global_checks.jl b/test/global_checks.jl index a880f9c7..2e6ac76c 100644 --- a/test/global_checks.jl +++ b/test/global_checks.jl @@ -2,33 +2,27 @@ struct BadConstructor x end -if VERSION >= v"1.3" - @testset "global_checks.jl" begin - test_method_tables() - ChainRulesCore.rrule(::typeof(BadConstructor), x) = nothing - @test fails(test_method_tables) - Base.delete_method(Base.which(rrule, (DataType, Any))) - test_method_tables() # make sure delete worked +@testset "global_checks.jl" begin + test_method_tables() + ChainRulesCore.rrule(::typeof(BadConstructor), x) = nothing + @test fails(test_method_tables) + Base.delete_method(Base.which(rrule, (DataType, Any))) + test_method_tables() # make sure delete worked - ChainRulesCore.rrule(::RuleConfig, ::typeof(BadConstructor), x) = nothing - @test fails(test_method_tables) - Base.delete_method(Base.which(rrule, (RuleConfig, DataType, Any))) - test_method_tables() # make sure delete worked + ChainRulesCore.rrule(::RuleConfig, ::typeof(BadConstructor), x) = nothing + @test fails(test_method_tables) + Base.delete_method(Base.which(rrule, (RuleConfig, DataType, Any))) + test_method_tables() # make sure delete worked - ChainRulesCore.frule(::Any, ::typeof(BadConstructor), x) = nothing - @test fails(test_method_tables) - Base.delete_method(Base.which(frule, (Any, DataType, Any))) - test_method_tables() # make sure delete worked + ChainRulesCore.frule(::Any, ::typeof(BadConstructor), x) = nothing + @test fails(test_method_tables) + Base.delete_method(Base.which(frule, (Any, DataType, Any))) + test_method_tables() # make sure delete worked - ChainRulesCore.frule(::RuleConfig, ::Any, ::typeof(BadConstructor), x) = nothing - @test fails(test_method_tables) - Base.delete_method(Base.which(frule, (RuleConfig, Any, DataType, Any))) - test_method_tables() # make sure delete worked - end -else # pre 1.3, so no `delete_method` so just test happy path - @testset "global_checks.jl" begin - test_method_tables() - end -end \ No newline at end of file + ChainRulesCore.frule(::RuleConfig, ::Any, ::typeof(BadConstructor), x) = nothing + @test fails(test_method_tables) + Base.delete_method(Base.which(frule, (RuleConfig, Any, DataType, Any))) + test_method_tables() # make sure delete worked +end diff --git a/test/rand_tangent.jl b/test/rand_tangent.jl index 4e76e3b4..a141c499 100644 --- a/test/rand_tangent.jl +++ b/test/rand_tangent.jl @@ -107,8 +107,7 @@ struct Bar @test x + (rand_tangent(x) + rand_tangent(x)) isa typeof(x) end - # Julia 1.6 changed to using Ryu printing algorithm and seems better at printing short - VERSION >= v"1.6" && @testset "niceness of printing" begin + @testset "niceness of printing" begin rng = MersenneTwister(1) for i in 1:50 @test length(string(rand_tangent(rng, 1.0))) <= 6 From 84d2a1b0676855c1ddf2a974457d1e8d0a0eb2ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller-Widmann?= Date: Tue, 20 Oct 2026 16:01:45 +0200 Subject: [PATCH 4/4] Only import `Test.eval_test` on Julia < 1.13 Since JuliaLang/julia@d934b03 (1.13.0-DEV.300) `Test.eval_test` is replaced by `eval_test_comparison` and `eval_test_function`, so importing it unconditionally warns that the imported binding was undeclared. Co-Authored-By: Claude Opus 5.5 --- src/output_control.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/output_control.jl b/src/output_control.jl index 12d9a9f1..2d1a6629 100644 --- a/src/output_control.jl +++ b/src/output_control.jl @@ -1,10 +1,12 @@ # Test.get_test_result generates code that uses the following so we must import them -using Test: Returned, Threw, eval_test +using Test: Returned, Threw @static if VERSION >= v"1.13.0-DEV.300" # https://github.com/JuliaLang/julia/commit/d934b032ea5bf63b353371ad285605128c735873 - # used by `Test.do_test` in `macro test_msg` + # replaced `eval_test` by `eval_test_comparison` and `eval_test_function` using Test: eval_test_comparison, eval_test_function +else + using Test: eval_test end "A cunning hack to carry extra message along with the original expression in a test"