Skip to content
Merged
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
24 changes: 24 additions & 0 deletions BREAKINGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,30 @@

This document outlines all breaking changes introduced in CTBase v0.18.0-beta compared to v0.17.4. Use this guide to migrate your code and understand the impact of these changes.

## Breaking changes (0.25.0-beta)

- **`NotProvided` / `NotProvidedType` removed from `CTBase.Options`.** They now live and are
exported **only** in `CTBase.Core`. `CTBase.Options.NotProvided` and
`CTBase.Options.NotProvidedType` no longer exist, and `using CTBase.Options` no longer
brings these names into scope.

**Migration:** replace `Options.NotProvided` → `Core.NotProvided` and
`Options.NotProvidedType` → `Core.NotProvidedType` (fully qualified: `CTBase.Core.NotProvided`).

```julia
# before
using CTBase.Options
OptionDefinition(name=:x, type=Int, default=NotProvided)

# after
import CTBase.Core
using CTBase.Options
OptionDefinition(name=:x, type=Int, default=Core.NotProvided)
```

- `NotStored` / `NotStoredType` are unchanged and remain extraction-internal to
`CTBase.Options` (the defining file was renamed `not_provided.jl` → `not_stored.jl`).

## Non-breaking note (0.24.0-beta)

- **Differentiation module**: Added comprehensive AD backend infrastructure for computing gradients
Expand Down
17 changes: 17 additions & 0 deletions CHANGELOGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ All notable changes to CTBase will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.25.0-beta] - 2026-06-26

### ⚠️ Breaking Changes

- **NotProvided moved to Core (no re-export)**: `NotProvidedType` and `NotProvided` are now
defined and exported **only** from `CTBase.Core`. They are **no longer available** from
`CTBase.Options` — `CTBase.Options.NotProvided` / `CTBase.Options.NotProvidedType` no longer
exist. Replace any `Options.NotProvided` usage with `Core.NotProvided` (or
`CTBase.Core.NotProvided`).
- `CTBase.Core.NotProvided` is the canonical ecosystem-wide "not provided" sentinel.

### 🔄 Refactoring

- `CTBase.Options` now only defines the extraction-internal `NotStored` / `NotStoredType`
sentinels (file renamed `not_provided.jl` → `not_stored.jl`). Internal Options/Strategies
code references `Core.NotProvidedType` directly.

## [0.24.0-beta] - 2026-06-25

### ✨ New Features
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "CTBase"
uuid = "54762871-cc72-4466-b8e8-f6c8b58076cd"
version = "0.24.0-beta"
version = "0.25.0-beta"
authors = ["Olivier Cots <olivier.cots@irit.fr>", "Jean-Baptiste Caillau <caillau@univ-cotedazur.fr>"]

[deps]
Expand Down
2 changes: 2 additions & 0 deletions src/Core/Core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import DocStringExtensions: TYPEDEF, TYPEDSIGNATURES
include("types.jl")
include("tags.jl")
include("caches.jl")
include("not_provided.jl")
include("default.jl")

# Private utilities
Expand All @@ -27,6 +28,7 @@ include("display.jl")
# Export public API
export ctNumber, matrix2vec, to_out_of_place, make_coerce, @ensure
export AbstractTag, AbstractCache
export NotProvided, NotProvidedType
export Style, Palette
export DEFAULT_PALETTE, MONOCHROME_PALETTE, HIGH_CONTRAST_PALETTE
export current_palette, set_palette!, set_color!, reset_palette!, show_palette
Expand Down
39 changes: 39 additions & 0 deletions src/Core/not_provided.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""
$(TYPEDEF)

Singleton type marking the absence of a provided value.

Ecosystem-wide sentinel for "no default / argument not given". The canonical
value is [`NotProvided`](@ref).

See also: [`NotProvided`](@ref).
"""
struct NotProvidedType end

"""
NotProvided

Singleton instance of [`NotProvidedType`](@ref).

The canonical "not provided" sentinel used across the control-toolbox ecosystem
(option defaults, optional variable parameters, optional AD backends, …).

# Example
```julia-repl
julia> using CTBase.Core

julia> x = NotProvided
NotProvided

julia> x isa NotProvidedType
true

julia> x === NotProvided
true
```

See also: [`NotProvidedType`](@ref).
"""
const NotProvided = NotProvidedType()

Base.show(io::IO, ::NotProvidedType) = print(io, "NotProvided")
3 changes: 1 addition & 2 deletions src/Options/Options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,13 @@ import CTBase.Core
import CTBase.Exceptions

# Submodules
include(joinpath(@__DIR__, "not_provided.jl"))
include(joinpath(@__DIR__, "not_stored.jl"))
include(joinpath(@__DIR__, "option_value.jl"))
include(joinpath(@__DIR__, "option_definition.jl"))
include(joinpath(@__DIR__, "extraction.jl"))

# Public API

export NotProvided, NotProvidedType
export OptionValue, OptionDefinition, extract_option, extract_options, extract_raw_options
export all_names, aliases
export is_user, is_default, is_computed # is_computed works for both OptionValue and OptionDefinition
Expand Down
6 changes: 3 additions & 3 deletions src/Options/extraction.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ function extract_option(kwargs::NamedTuple, def::OptionDefinition)
end

# Not found - check if default is NotProvided
if def.default isa NotProvidedType
if def.default isa Core.NotProvidedType
# No default and not provided by user - return NotStored to signal "don't store"
return NotStored, kwargs
end
Expand Down Expand Up @@ -223,7 +223,7 @@ builders to use their own defaults. Options with explicit `nothing` values are i
opts = (backend = OptionValue(:optimized, :user),
show_time = OptionValue(false, :default),
minimize = OptionValue(nothing, :default),
optional = OptionValue(NotProvided, :default))
optional = OptionValue(CTBase.Core.NotProvided, :default))

extract_raw_options(opts)
# (backend = :optimized, show_time = false, minimize = nothing)
Expand All @@ -236,7 +236,7 @@ function extract_raw_options(options::NamedTuple)
for (k, v) in pairs(options)
val = v isa OptionValue ? v.value : v
# Filter out NotProvided values, but keep nothing values
if !(val isa NotProvidedType)
if !(val isa Core.NotProvidedType)
raw_opts_dict[k] = val
end
end
Expand Down
98 changes: 0 additions & 98 deletions src/Options/not_provided.jl

This file was deleted.

30 changes: 30 additions & 0 deletions src/Options/not_stored.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""
$(TYPEDEF)

Internal sentinel type used by the option extraction system to signal that an option
should not be stored in the instance.

This is returned by `extract_option` when an option has [`CTBase.Core.NotProvided`](@ref)
as its default and was not provided by the user.

# Note
This type is internal to the Options module and should not be used directly by users.
Use [`CTBase.Core.NotProvided`](@ref) instead.

See also: [`CTBase.Core.NotProvided`](@ref), [`extract_option`](@ref).
"""
struct NotStoredType end

"""
NotStored

Internal singleton instance of [`NotStoredType`](@ref).

Used internally by the option extraction system to signal that an option should not
be stored. This is distinct from `nothing` which is a valid option value.

See also: [`CTBase.Core.NotProvided`](@ref), [`extract_option`](@ref).
"""
const NotStored = NotStoredType()

Base.show(io::IO, ::NotStoredType) = print(io, "NotStored")
16 changes: 8 additions & 8 deletions src/Options/option_definition.jl
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ struct OptionDefinition{T}
computed::Bool=false,
) where {T}
# Validate with custom validator if provided (skip for NotProvided)
if validator !== nothing && !(default isa NotProvidedType)
if validator !== nothing && !(default isa Core.NotProvidedType)
try
validator(default)
catch e
Expand Down Expand Up @@ -152,7 +152,7 @@ julia> # No default - creates NotProvidedType
julia> def3 = OptionDefinition(
name = :input_file,
type = String,
default = NotProvided,
default = CTBase.Core.NotProvided,
description = "Input file path"
)
OptionDefinition{NotProvidedType}(...)
Expand Down Expand Up @@ -270,7 +270,7 @@ julia> using CTBase.Options
julia> def = _construct_option_definition(
:input_file,
String,
NotProvided,
CTBase.Core.NotProvided,
"Input file path",
(:input,)
)
Expand All @@ -285,13 +285,13 @@ See also: `OptionDefinition`, `NotProvided`, `is_required`
function _construct_option_definition(
name::Symbol,
type::Type,
default::NotProvidedType,
default::Core.NotProvidedType,
description::String,
aliases::Tuple{Vararg{Symbol}},
validator::Union{Function,Nothing},
computed::Bool,
)
return OptionDefinition{NotProvidedType}(;
return OptionDefinition{Core.NotProvidedType}(;
name=name,
type=type,
default=default,
Expand Down Expand Up @@ -543,7 +543,7 @@ Returns `true` when the default value is `NotProvided`.
```julia-repl
julia> using CTBase.Options

julia> def = OptionDefinition(name=:input, type=String, default=NotProvided,
julia> def = OptionDefinition(name=:input, type=String, default=CTBase.Core.NotProvided,
description="Input file")
OptionDefinition{NotProvidedType}(...)

Expand All @@ -553,7 +553,7 @@ true

See also: `has_default`, `default`
"""
is_required(def::OptionDefinition) = def.default isa NotProvidedType
is_required(def::OptionDefinition) = def.default isa Core.NotProvidedType

"""
$(TYPEDSIGNATURES)
Expand All @@ -579,7 +579,7 @@ true

See also: `is_required`, `default`
"""
has_default(def::OptionDefinition) = !(def.default isa NotProvidedType)
has_default(def::OptionDefinition) = !(def.default isa Core.NotProvidedType)

"""
$(TYPEDSIGNATURES)
Expand Down
3 changes: 2 additions & 1 deletion test/suite/options/test_coverage_options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module TestCoverageOptions
using Test: Test
import CTBase.Exceptions
import CTBase.Options
import CTBase.Core
import CTBase.Strategies

const VERBOSE = isdefined(Main, :TestData) ? Main.TestData.VERBOSE : true
Expand Down Expand Up @@ -43,7 +44,7 @@ function test_coverage_options()

Test.@testset "NotProvided display" begin
buf = IOBuffer()
show(buf, Options.NotProvided)
show(buf, Core.NotProvided)
Test.@test String(take!(buf)) == "NotProvided"
end

Expand Down
Loading