Skip to content

Commit defd8ac

Browse files
ocotsclaude
andcommitted
refactor!: move NotProvided/NotProvidedType to Core (remove from Options)
NotProvidedType and NotProvided are now defined and exported ONLY from CTBase.Core as the canonical ecosystem-wide sentinel. They are removed from CTBase.Options (no re-export): Options.NotProvided / Options.NotProvidedType no longer exist. - Options/not_provided.jl renamed to not_stored.jl (keeps NotStored only). - Internal Options/extraction + option_definition reference Core.NotProvidedType. - Tests repointed to Core.NotProvided. BREAKING: replace Options.NotProvided -> Core.NotProvided. Bump 0.25.0-beta. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 581b424 commit defd8ac

16 files changed

Lines changed: 167 additions & 151 deletions

BREAKINGS.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,30 @@
22

33
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.
44

5+
## Breaking changes (0.25.0-beta)
6+
7+
- **`NotProvided` / `NotProvidedType` removed from `CTBase.Options`.** They now live and are
8+
exported **only** in `CTBase.Core`. `CTBase.Options.NotProvided` and
9+
`CTBase.Options.NotProvidedType` no longer exist, and `using CTBase.Options` no longer
10+
brings these names into scope.
11+
12+
**Migration:** replace `Options.NotProvided``Core.NotProvided` and
13+
`Options.NotProvidedType``Core.NotProvidedType` (fully qualified: `CTBase.Core.NotProvided`).
14+
15+
```julia
16+
# before
17+
using CTBase.Options
18+
OptionDefinition(name=:x, type=Int, default=NotProvided)
19+
20+
# after
21+
import CTBase.Core
22+
using CTBase.Options
23+
OptionDefinition(name=:x, type=Int, default=Core.NotProvided)
24+
```
25+
26+
- `NotStored` / `NotStoredType` are unchanged and remain extraction-internal to
27+
`CTBase.Options` (the defining file was renamed `not_provided.jl``not_stored.jl`).
28+
529
## Non-breaking note (0.24.0-beta)
630

731
- **Differentiation module**: Added comprehensive AD backend infrastructure for computing gradients

CHANGELOGS.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,23 @@ All notable changes to CTBase will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.25.0-beta] - 2026-06-26
9+
10+
### ⚠️ Breaking Changes
11+
12+
- **NotProvided moved to Core (no re-export)**: `NotProvidedType` and `NotProvided` are now
13+
defined and exported **only** from `CTBase.Core`. They are **no longer available** from
14+
`CTBase.Options``CTBase.Options.NotProvided` / `CTBase.Options.NotProvidedType` no longer
15+
exist. Replace any `Options.NotProvided` usage with `Core.NotProvided` (or
16+
`CTBase.Core.NotProvided`).
17+
- `CTBase.Core.NotProvided` is the canonical ecosystem-wide "not provided" sentinel.
18+
19+
### 🔄 Refactoring
20+
21+
- `CTBase.Options` now only defines the extraction-internal `NotStored` / `NotStoredType`
22+
sentinels (file renamed `not_provided.jl``not_stored.jl`). Internal Options/Strategies
23+
code references `Core.NotProvidedType` directly.
24+
825
## [0.24.0-beta] - 2026-06-25
926

1027
### ✨ New Features

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "CTBase"
22
uuid = "54762871-cc72-4466-b8e8-f6c8b58076cd"
3-
version = "0.24.0-beta"
3+
version = "0.25.0-beta"
44
authors = ["Olivier Cots <olivier.cots@irit.fr>", "Jean-Baptiste Caillau <caillau@univ-cotedazur.fr>"]
55

66
[deps]

src/Core/Core.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import DocStringExtensions: TYPEDEF, TYPEDSIGNATURES
1313
include("types.jl")
1414
include("tags.jl")
1515
include("caches.jl")
16+
include("not_provided.jl")
1617
include("default.jl")
1718

1819
# Private utilities
@@ -27,6 +28,7 @@ include("display.jl")
2728
# Export public API
2829
export ctNumber, matrix2vec, to_out_of_place, make_coerce, @ensure
2930
export AbstractTag, AbstractCache
31+
export NotProvided, NotProvidedType
3032
export Style, Palette
3133
export DEFAULT_PALETTE, MONOCHROME_PALETTE, HIGH_CONTRAST_PALETTE
3234
export current_palette, set_palette!, set_color!, reset_palette!, show_palette

src/Core/not_provided.jl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""
2+
$(TYPEDEF)
3+
4+
Singleton type marking the absence of a provided value.
5+
6+
Ecosystem-wide sentinel for "no default / argument not given". The canonical
7+
value is [`NotProvided`](@ref).
8+
9+
See also: [`NotProvided`](@ref).
10+
"""
11+
struct NotProvidedType end
12+
13+
"""
14+
NotProvided
15+
16+
Singleton instance of [`NotProvidedType`](@ref).
17+
18+
The canonical "not provided" sentinel used across the control-toolbox ecosystem
19+
(option defaults, optional variable parameters, optional AD backends, …).
20+
21+
# Example
22+
```julia-repl
23+
julia> using CTBase.Core
24+
25+
julia> x = NotProvided
26+
NotProvided
27+
28+
julia> x isa NotProvidedType
29+
true
30+
31+
julia> x === NotProvided
32+
true
33+
```
34+
35+
See also: [`NotProvidedType`](@ref).
36+
"""
37+
const NotProvided = NotProvidedType()
38+
39+
Base.show(io::IO, ::NotProvidedType) = print(io, "NotProvided")

src/Options/Options.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,13 @@ import CTBase.Core
1818
import CTBase.Exceptions
1919

2020
# Submodules
21-
include(joinpath(@__DIR__, "not_provided.jl"))
21+
include(joinpath(@__DIR__, "not_stored.jl"))
2222
include(joinpath(@__DIR__, "option_value.jl"))
2323
include(joinpath(@__DIR__, "option_definition.jl"))
2424
include(joinpath(@__DIR__, "extraction.jl"))
2525

2626
# Public API
2727

28-
export NotProvided, NotProvidedType
2928
export OptionValue, OptionDefinition, extract_option, extract_options, extract_raw_options
3029
export all_names, aliases
3130
export is_user, is_default, is_computed # is_computed works for both OptionValue and OptionDefinition

src/Options/extraction.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ function extract_option(kwargs::NamedTuple, def::OptionDefinition)
7777
end
7878

7979
# Not found - check if default is NotProvided
80-
if def.default isa NotProvidedType
80+
if def.default isa Core.NotProvidedType
8181
# No default and not provided by user - return NotStored to signal "don't store"
8282
return NotStored, kwargs
8383
end
@@ -223,7 +223,7 @@ builders to use their own defaults. Options with explicit `nothing` values are i
223223
opts = (backend = OptionValue(:optimized, :user),
224224
show_time = OptionValue(false, :default),
225225
minimize = OptionValue(nothing, :default),
226-
optional = OptionValue(NotProvided, :default))
226+
optional = OptionValue(CTBase.Core.NotProvided, :default))
227227
228228
extract_raw_options(opts)
229229
# (backend = :optimized, show_time = false, minimize = nothing)
@@ -236,7 +236,7 @@ function extract_raw_options(options::NamedTuple)
236236
for (k, v) in pairs(options)
237237
val = v isa OptionValue ? v.value : v
238238
# Filter out NotProvided values, but keep nothing values
239-
if !(val isa NotProvidedType)
239+
if !(val isa Core.NotProvidedType)
240240
raw_opts_dict[k] = val
241241
end
242242
end

src/Options/not_provided.jl

Lines changed: 0 additions & 98 deletions
This file was deleted.

src/Options/not_stored.jl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""
2+
$(TYPEDEF)
3+
4+
Internal sentinel type used by the option extraction system to signal that an option
5+
should not be stored in the instance.
6+
7+
This is returned by `extract_option` when an option has [`CTBase.Core.NotProvided`](@ref)
8+
as its default and was not provided by the user.
9+
10+
# Note
11+
This type is internal to the Options module and should not be used directly by users.
12+
Use [`CTBase.Core.NotProvided`](@ref) instead.
13+
14+
See also: [`CTBase.Core.NotProvided`](@ref), [`extract_option`](@ref).
15+
"""
16+
struct NotStoredType end
17+
18+
"""
19+
NotStored
20+
21+
Internal singleton instance of [`NotStoredType`](@ref).
22+
23+
Used internally by the option extraction system to signal that an option should not
24+
be stored. This is distinct from `nothing` which is a valid option value.
25+
26+
See also: [`CTBase.Core.NotProvided`](@ref), [`extract_option`](@ref).
27+
"""
28+
const NotStored = NotStoredType()
29+
30+
Base.show(io::IO, ::NotStoredType) = print(io, "NotStored")

src/Options/option_definition.jl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ struct OptionDefinition{T}
8585
computed::Bool=false,
8686
) where {T}
8787
# Validate with custom validator if provided (skip for NotProvided)
88-
if validator !== nothing && !(default isa NotProvidedType)
88+
if validator !== nothing && !(default isa Core.NotProvidedType)
8989
try
9090
validator(default)
9191
catch e
@@ -152,7 +152,7 @@ julia> # No default - creates NotProvidedType
152152
julia> def3 = OptionDefinition(
153153
name = :input_file,
154154
type = String,
155-
default = NotProvided,
155+
default = CTBase.Core.NotProvided,
156156
description = "Input file path"
157157
)
158158
OptionDefinition{NotProvidedType}(...)
@@ -270,7 +270,7 @@ julia> using CTBase.Options
270270
julia> def = _construct_option_definition(
271271
:input_file,
272272
String,
273-
NotProvided,
273+
CTBase.Core.NotProvided,
274274
"Input file path",
275275
(:input,)
276276
)
@@ -285,13 +285,13 @@ See also: `OptionDefinition`, `NotProvided`, `is_required`
285285
function _construct_option_definition(
286286
name::Symbol,
287287
type::Type,
288-
default::NotProvidedType,
288+
default::Core.NotProvidedType,
289289
description::String,
290290
aliases::Tuple{Vararg{Symbol}},
291291
validator::Union{Function,Nothing},
292292
computed::Bool,
293293
)
294-
return OptionDefinition{NotProvidedType}(;
294+
return OptionDefinition{Core.NotProvidedType}(;
295295
name=name,
296296
type=type,
297297
default=default,
@@ -543,7 +543,7 @@ Returns `true` when the default value is `NotProvided`.
543543
```julia-repl
544544
julia> using CTBase.Options
545545
546-
julia> def = OptionDefinition(name=:input, type=String, default=NotProvided,
546+
julia> def = OptionDefinition(name=:input, type=String, default=CTBase.Core.NotProvided,
547547
description="Input file")
548548
OptionDefinition{NotProvidedType}(...)
549549
@@ -553,7 +553,7 @@ true
553553
554554
See also: `has_default`, `default`
555555
"""
556-
is_required(def::OptionDefinition) = def.default isa NotProvidedType
556+
is_required(def::OptionDefinition) = def.default isa Core.NotProvidedType
557557

558558
"""
559559
$(TYPEDSIGNATURES)
@@ -579,7 +579,7 @@ true
579579
580580
See also: `is_required`, `default`
581581
"""
582-
has_default(def::OptionDefinition) = !(def.default isa NotProvidedType)
582+
has_default(def::OptionDefinition) = !(def.default isa Core.NotProvidedType)
583583

584584
"""
585585
$(TYPEDSIGNATURES)

0 commit comments

Comments
 (0)