Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/src/functions.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@

## What counts as public API

A name is public if it is exported, or if it is declared `public`. On Julia
1.11 and newer both cases answer `true` to `Base.ispublic(SBML, name)`, which
is the authoritative check. Anything else — including some parser and math
helpers that this reference still renders, such as the
[internal math helpers](#Internal-math-helpers) — may change in any release.

Much of the public API is deliberately *not* exported, so that `using SBML`
does not bring generic names such as `Model`, `Species` or `Version` into your
namespace. Reach those through the module instead: `SBML.Model`,
`SBML.MathApply`, `SBML.extensive_kinetic_math`, and so on.

Julia has no field-level visibility, so a public struct type also makes its
documented fields (listed under each type below) part of the public API.

# Data types

## Helper types
Expand Down
75 changes: 75 additions & 0 deletions src/SBML.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,81 @@ export writeSBML
export set_level_and_version,
libsbml_convert, convert_simplify_math, convert_promotelocals_expandfuns

# The names below are documented API that is deliberately not exported, to keep
# `using SBML` from polluting the namespace with generic names like `Model`,
# `Parameter` or `Version`. Downstream packages are expected to reach them as
# `SBML.Model` etc., so they are declared `public`.
#
# `public` is a Julia 1.11 feature and this package still supports 1.6, so the
# declaration goes through `eval` behind a version guard; a bare `public ...`
# would be a syntax error on older versions. Julia has no field-level
# visibility, so for the struct types here the documented fields (rendered from
# `$(TYPEDFIELDS)`) are covered by the type being public.
@static if VERSION >= v"1.11"
eval(
Expr(
:public,
# types.jl
:Maybe,
:VPtr,
# structs.jl
:SBMLObject,
:UnitPart,
:UnitDefinition,
:GeneProductAssociation,
:GPARef,
:GPAAnd,
:GPAOr,
:Math,
:MathVal,
:MathIdent,
:MathConst,
:MathTime,
:MathAvogadro,
:MathApply,
:MathLambda,
:CVTerm,
:Parameter,
:Compartment,
:SpeciesReference,
:Reaction,
:Rule,
:AlgebraicRule,
:AssignmentRule,
:RateRule,
:Constraint,
:Species,
:GeneProduct,
:FunctionDefinition,
:EventAssignment,
:Trigger,
:Objective,
:Event,
:Member,
:Group,
:Model,
# version.jl
:Version,
# interpret.jl
:interpret_math,
:default_function_mapping,
:default_constants,
# unitful.jl
:unitful,
# utils.jl
:extensive_kinetic_math,
:fbc_flux_objective,
:kinetic_flux_objective,
:get_compartment_size,
:initial_amounts,
:initial_concentrations,
:isfreein,
:seemsdefined,
:test_suite_url,
),
)
end

# Read a file at precompile time, to improve time-to-first `readSBML`.
writeSBML(readSBML(joinpath(@__DIR__, "..", "test", "data", "Dasgupta2020-written.xml")))

Expand Down
74 changes: 74 additions & 0 deletions test/public.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
const PUBLIC_NOT_EXPORTED = [
:Maybe,
:VPtr,
:SBMLObject,
:UnitPart,
:UnitDefinition,
:GeneProductAssociation,
:GPARef,
:GPAAnd,
:GPAOr,
:Math,
:MathVal,
:MathIdent,
:MathConst,
:MathTime,
:MathAvogadro,
:MathApply,
:MathLambda,
:CVTerm,
:Parameter,
:Compartment,
:SpeciesReference,
:Reaction,
:Rule,
:AlgebraicRule,
:AssignmentRule,
:RateRule,
:Constraint,
:Species,
:GeneProduct,
:FunctionDefinition,
:EventAssignment,
:Trigger,
:Objective,
:Event,
:Member,
:Group,
:Model,
:Version,
:interpret_math,
:default_function_mapping,
:default_constants,
:unitful,
:extensive_kinetic_math,
:fbc_flux_objective,
:kinetic_flux_objective,
:get_compartment_size,
:initial_amounts,
:initial_concentrations,
:isfreein,
:seemsdefined,
:test_suite_url,
]

@testset "Public API" begin
@testset "$name is defined and documented" for name in PUBLIC_NOT_EXPORTED
@test isdefined(SBML, name)
@test haskey(Docs.meta(SBML), Docs.Binding(SBML, name))
end

if VERSION >= v"1.11"
@testset "$name is public and unexported" for name in PUBLIC_NOT_EXPORTED
@test Base.ispublic(SBML, name)
@test !Base.isexported(SBML, name)
end

@testset "every name reachable by `using SBML` is public" begin
for name in names(SBML)
name === :SBML && continue
@test Base.ispublic(SBML, name)
end
end
end
end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ include("common.jl")

@testset "SBML test suite" begin
include("version.jl")
include("public.jl")

if TEST_SYMBOLICS
# this defines a few functions used also in loadmodels.jl
Expand Down