From 1fb782d56e2364688350ac219e1c5ce75e3d5701 Mon Sep 17 00:00:00 2001 From: tan_unique <143566827+vinson0522@users.noreply.github.com> Date: Fri, 14 Aug 2026 07:59:10 +0000 Subject: [PATCH 1/3] Convert ruamel YAML scalars to builtin types on load --- box/converters.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/box/converters.py b/box/converters.py index bb91ba6..d072cd5 100644 --- a/box/converters.py +++ b/box/converters.py @@ -233,6 +233,30 @@ def _to_yaml( raise BoxError(MISSING_PARSER_ERROR) + +def _ruamel_to_builtin(obj): + """Convert ruamel.yaml scalar types to plain Python builtins. + + ScalarFloat/ScalarInt survive Box.to_dict() and break serializers + that only accept builtin float/int (issue #264). + """ + if isinstance(obj, dict): + return {k: _ruamel_to_builtin(v) for k, v in obj.items()} + if isinstance(obj, list): + return [_ruamel_to_builtin(v) for v in obj] + module = type(obj).__module__ + if module.startswith("ruamel"): + if isinstance(obj, bool): + return bool(obj) + if isinstance(obj, int): + return int(obj) + if isinstance(obj, float): + return float(obj) + if isinstance(obj, str): + return str(obj) + return obj + + def _from_yaml( yaml_string: str | None = None, filename: str | PathLike | None = None, @@ -272,7 +296,7 @@ def _from_yaml( raise BoxError(MISSING_PARSER_ERROR) else: raise BoxError("from_yaml requires a string or filename") - return data + return _ruamel_to_builtin(data) def _to_toml(obj, filename: str | PathLike | None = None, encoding: str = "utf-8", errors: str = "strict"): From 41f83c32558ffa9223d248a9cb1a48660312c52e Mon Sep 17 00:00:00 2001 From: tan_unique <143566827+vinson0522@users.noreply.github.com> Date: Fri, 14 Aug 2026 07:59:11 +0000 Subject: [PATCH 2/3] Test from_yaml returns builtin float/int/bool --- test/test_box.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/test_box.py b/test/test_box.py index e5c56e0..7f8f562 100644 --- a/test/test_box.py +++ b/test/test_box.py @@ -369,6 +369,17 @@ def test_from_yaml(self): assert bx.key1 == "value1" assert bx.Key_2 == Box() + + def test_from_yaml_builtin_scalars(self): + bx = Box.from_yaml("Float: 0.1\nCount: 4\nFlag: true\n") + assert type(bx.Float) is float + assert type(bx.Count) is int + assert type(bx.Flag) is bool + dumped = bx.to_dict() + assert type(dumped["Float"]) is float + assert type(dumped["Count"]) is int + assert dumped["Float"] == 0.1 + def test_bad_from_json(self): with pytest.raises(BoxError): Box.from_json() From a7d3f152ed048719229d19d16e6d170cff896c39 Mon Sep 17 00:00:00 2001 From: tan_unique <143566827+vinson0522@users.noreply.github.com> Date: Fri, 14 Aug 2026 07:59:12 +0000 Subject: [PATCH 3/3] Note #264 ScalarFloat fix in changelog --- CHANGES.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index c4a347d..829d9a3 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,11 @@ Changelog ========= +Version 7.4.2 +------------- + +* Fixing #264 ruamel.yaml ScalarFloat/ScalarInt kept as non-builtin types after from_yaml + Version 7.4.1 -------------