omry / omegaconf

Flexible Python configuration system. The last one you will ever need.
BSD 3-Clause "New" or "Revised" License
1.97k stars 109 forks source link

Structured config type coercion not working correctly for DictConfig keys #1037

Open petosa opened 1 year ago

petosa commented 1 year ago

Describe the bug DictConfig keys do not support the same type coercion as other typed fields. For example, floats and strings are not coerced to ints for DictConfig keys, while other fields have no issue. For some reason, enum coercion seems to be the only thing that works correctly for DictConfig keys. Additionally, ListConfig type and DictConfig value type coercion seems to work just fine.

To Reproduce

import omegaconf
from omegaconf import MISSING, OmegaConf
import dataclasses
from enum import Enum

class Color(Enum):
    red = "RED"
    blue = "BLUE"

@dataclasses.dataclass
class Example:
    a: float = MISSING  # Coerces correctly
    b: dict[Color, Color] = MISSING  # Coerces correctly
    c: dict[float, Color] = MISSING  # Coerces INCORRECTLY
    d: dict[Color, float] = MISSING  # Coerces correctly
    e: list[float] = MISSING  # Coerces correctly

struct = OmegaConf.structured(Example)

cfg  = OmegaConf.create(
    {
        "a":3,
        "b":{"red":"blue"},
        "c":{3: "blue"},
        "d": {"red":4} ,
        "e":[3,4]
    }
)

merged = OmegaConf.merge(struct, cfg)
print(merged)

Expected behavior I would expect the above code to print {'a': 3.0, 'b': {<Color.red: 'RED'>: <Color.blue: 'BLUE'>}, 'c': {3.0: <Color.blue: 'BLUE'>}, 'd': {<Color.red: 'RED'>: 4.0}, 'e': [3.0, 4.0]} And I do get this output if I change "c":{3: "blue"} to "c":{3.0: "blue"}

Instead I get:

omegaconf.errors.KeyValidationError: Key 3 (int) is incompatible with (float)
full_key: c.3
reference_type=Dict[float, Color]
object_type=dict

I would expect DictConfig keys to be coerced in the same way as DictConfig values, or other fields in general.

Additional context