diff --git a/CHANGELOG.md b/CHANGELOG.md index 88f6b4c13..6e0a7efe3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ## Unreleased +### Added + +* All the public API names are now correctly marked `public` in Julia 1.11 and above. ([#83]) + ### Fixed * The `JuliaHub.update_dataset` function now correctly accepts the `license=(:fulltext, ...)` argument. ([#74]) @@ -141,3 +145,4 @@ Initial package release. [#53]: https://github.com/JuliaComputing/JuliaHub.jl/issues/53 [#58]: https://github.com/JuliaComputing/JuliaHub.jl/issues/58 [#74]: https://github.com/JuliaComputing/JuliaHub.jl/issues/74 +[#83]: https://github.com/JuliaComputing/JuliaHub.jl/issues/83 diff --git a/src/JuliaHub.jl b/src/JuliaHub.jl index b371d3541..4121e06d8 100644 --- a/src/JuliaHub.jl +++ b/src/JuliaHub.jl @@ -38,4 +38,31 @@ function __init__() _LOCAL_TZ[] = _localtz() end +# JuliaHub.jl follows the convention that all private names are +# prefixed with an underscore. +function _find_public_names() + return filter(names(@__MODULE__; all=true)) do s + # We don't need to check or mark public the main module itself + (s == :JuliaHub) && return false + startswith(string(s), "_") && return false + # Internal functions and types, prefixed by _ + startswith(string(s), "_") && return false + # Internal macros, prefixed by _ + startswith(string(s), "@_") && return false + # Strange generated functions + startswith(string(s), "#") && return false + # Some core functions that are not relevant for the package + s in [:eval, :include] && return false + return true + end +end +macro _mark_names_public() + if !Base.isdefined(Base, :ispublic) + return nothing + end + public_names = _find_public_names() + return esc(Expr(:public, public_names...)) +end +@_mark_names_public + end diff --git a/test/runtests.jl b/test/runtests.jl index 51185a44e..d8a3b68b8 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -173,19 +173,7 @@ end # This set tests that we haven't accidentally added or removed any public-looking # functions (i.e. ones that are not prefixed by _ basically). @testset "Public API" begin - public_symbols = Set( - filter(names(JuliaHub; all=true)) do s - # Internal functions and types, prefixed by _ - startswith(string(s), "_") && return false - # Internal macros, prefixed by _ - startswith(string(s), "@_") && return false - # Strange generated functions - startswith(string(s), "#") && return false - # Some core functions that are not relevant for the package - s in [:eval, :include] && return false - return true - end, - ) + public_symbols = Set(JuliaHub._find_public_names()) expected_public_symbols = Set([ Symbol("@script_str"), :AbstractJobConfig, :AbstractJuliaHubApp, @@ -194,7 +182,7 @@ end :Dataset, :DatasetReference, :DatasetVersion, :DefaultApp, :FileHash, :InvalidAuthentication, :InvalidRequestError, :Job, :WorkloadConfig, :JobFile, :JobLogMessage, :JobReference, :JobStatus, - :JuliaHub, :JuliaHubConnectionError, :JuliaHubError, + :JuliaHubConnectionError, :JuliaHubError, :JuliaHubException, :Limit, :NodeSpec, :PackageApp, :PackageJob, :Unlimited, :PermissionError, :script, :Secret, :UserApp, @@ -223,6 +211,21 @@ end extra_expected_symbols = $(sprint(show, MIME"text/plain"(), extra_expected_symbols)) """ @test isempty(extra_expected_symbols) + # Make sure that on Julia versions that support the `public` keyword, + # we are also marking the right symbols as public. + if Base.isdefined(Base, :ispublic) + @testset "ispublic: $(name)" for name in public_symbols + @test Base.ispublic(JuliaHub, name) + end + private_names = setdiff( + names(JuliaHub; all=true), + public_symbols, + [:JuliaHub], + ) + @testset "!ispublic: $(name)" for name in private_names + @test !Base.ispublic(JuliaHub, name) + end + end end @testset "Utilities" begin