Migrate tuple usage to 2.4
OmegaConf 2.4 preserves native Python tuples as structurally immutable
TupleConfig values. Earlier releases converted them to mutable ListConfig
values. This is a breaking change if your code assumes every OmegaConf
sequence is a list or mutates a config created from a tuple.
What changed
>>> from omegaconf import OmegaConf
>>> cfg = OmegaConf.create({"coords": (1, 2)})
>>> OmegaConf.is_tuple(cfg.coords)
True
>>> OmegaConf.is_sequence(cfg.coords)
True
>>> OmegaConf.is_list(cfg.coords)
False
A TupleConfig does not allow elements to be inserted, removed, or replaced.
Nested mutable containers remain mutable. OmegaConf.to_container() converts
it back to a native tuple.
Choose the intended sequence type
If the value should be mutable, create it from a list:
>>> cfg = OmegaConf.create({"coords": list((1, 2))})
>>> cfg.coords.append(3)
>>> list(cfg.coords)
[1, 2, 3]
For a structured config, annotate mutable sequences as list[T] or
typing.List[T]. If the value is conceptually a tuple, keep the tuple input
or use a tuple annotation. Replace the complete value through its mutable
parent when needed:
>>> cfg = OmegaConf.create({"coords": (1, 2)})
>>> cfg.coords = (1, 2, 3)
>>> tuple(cfg.coords)
(1, 2, 3)
An untyped tuple accepts any length on replacement. A fixed annotation such
as tuple[int, int] requires two elements; tuple[int, ...] permits any
number of integers.
Update sequence checks
Use OmegaConf.is_tuple(value) for tuple-specific behavior,
OmegaConf.is_list(value) for mutable-list behavior, and
OmegaConf.is_sequence(value) when either kind of sequence is accepted.
Code that used isinstance(value, ListConfig) for general indexed traversal
should usually use OmegaConf.is_sequence(value).
Check code that appends to config sequences, assigns their elements, or expects tuple input to become a list. Tuple semantics remain experimental in 2.4; feedback is welcome in issue #392.