From 4d1d96a0aeb49070fbd9b46bff777ef1ddf257a3 Mon Sep 17 00:00:00 2001 From: Pere Diaz Bou <30913090+pereman2@users.noreply.github.com> Date: Fri, 24 Jul 2020 18:35:56 +0200 Subject: [PATCH] OmegaConf.to_yaml (#313) --- docs/notebook/Tutorial.ipynb | 102 ++++++++++------- docs/source/structured_config.rst | 4 +- docs/source/usage.rst | 24 ++-- news/263.removal | 1 + omegaconf/basecontainer.py | 24 ++-- omegaconf/omegaconf.py | 23 +++- tests/examples/test_dataclass_example.py | 2 +- tests/test_basic_ops_dict.py | 65 ----------- tests/test_basic_ops_list.py | 64 +---------- tests/test_nodes.py | 16 --- tests/test_to_yaml.py | 139 +++++++++++++++++++++++ 11 files changed, 245 insertions(+), 219 deletions(-) create mode 100644 news/263.removal create mode 100644 tests/test_to_yaml.py diff --git a/docs/notebook/Tutorial.ipynb b/docs/notebook/Tutorial.ipynb index 43411ce34..d37bd6ce4 100644 --- a/docs/notebook/Tutorial.ipynb +++ b/docs/notebook/Tutorial.ipynb @@ -75,7 +75,7 @@ ], "source": [ "conf = OmegaConf.create(dict(k='v',list=[1,dict(a='1',b='2')]))\n", - "print(conf.pretty())" + "print(OmegaConf.to_yaml(conf))" ] }, { @@ -108,7 +108,7 @@ ], "source": [ "conf = OmegaConf.create([1, dict(a=10, b=dict(a=10))])\n", - "print(conf.pretty())" + "print(OmegaConf.to_yaml(conf))" ] }, { @@ -145,7 +145,7 @@ ], "source": [ "conf = OmegaConf.load('../source/example.yaml')\n", - "print(conf.pretty())" + "print(OmegaConf.to_yaml(conf))" ] }, { @@ -186,7 +186,7 @@ "- item2\n", "\"\"\"\n", "conf = OmegaConf.create(yaml)\n", - "print(conf.pretty())" + "print(OmegaConf.to_yaml(conf))" ] }, { @@ -223,7 +223,7 @@ "source": [ "dot_list = [\"a.aa.aaa=1\", \"a.aa.bbb=2\", \"a.bb.aaa=3\", \"a.bb.bbb=4\"]\n", "conf = OmegaConf.from_dotlist(dot_list)\n", - "print(conf.pretty())" + "print(OmegaConf.to_yaml(conf))" ] }, { @@ -261,7 +261,7 @@ "import sys\n", "sys.argv = ['your-program.py', 'server.port=82', 'log.file=log2.txt']\n", "conf = OmegaConf.from_cli()\n", - "print(conf.pretty())" + "print(OmegaConf.to_yaml(conf))" ] }, { @@ -299,7 +299,7 @@ ], "source": [ "conf = OmegaConf.load('../source/example.yaml')\n", - "print(conf.pretty())" + "print(OmegaConf.to_yaml(conf))" ] }, { @@ -528,9 +528,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Interpolations are evaluated lazily on field access.
\n", - "Note below that when printed the interpolations are not resolved.
\n", - "They get resolved once you access them." + "Interpolations are evaluated lazily on field access. OmegaConf.to_yaml() is eagerly resolving the interpolations by default." ] }, { @@ -550,47 +548,52 @@ " host: localhost\n", " port: 80\n", "client:\n", - " url: http://${server.host}:${server.port}/\n", - " server_port: ${server.port}\n", + " url: http://localhost:80/\n", + " server_port: 80\n", "\n" ] } ], "source": [ "conf = OmegaConf.load('../source/config_interpolation.yaml')\n", - "print(conf.pretty())" + "print(OmegaConf.to_yaml(conf))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can change it by passing `resolve=False`." ] }, { "cell_type": "code", "execution_count": 18, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, + "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "conf.client.server_port: 80 int\n", - "conf.client.url: http://localhost:80/ str\n" + "server:\n", + " host: localhost\n", + " port: 80\n", + "client:\n", + " url: http://${server.host}:${server.port}/\n", + " server_port: ${server.port}\n", + "\n" ] } ], "source": [ - "# Primitive interpolation types are inherited from the referenced value\n", - "print(\"conf.client.server_port: \", conf.client.server_port, type(conf.client.server_port).__name__)\n", - "# Composite interpolation types are always string\n", - "print(\"conf.client.url: \", conf.client.url, type(conf.client.url).__name__)" + "print(OmegaConf.to_yaml(conf, resolve=False))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "You can resolve interpolation while you are printing using `resolve=True`." + "Notice that the url and server_port changes with the port." ] }, { @@ -602,18 +605,17 @@ "name": "stdout", "output_type": "stream", "text": [ - "server:\n", - " host: localhost\n", - " port: 80\n", - "client:\n", - " url: http://localhost:80/\n", - " server_port: 80\n", - "\n" + "conf.client.server_port: 90 int\n", + "conf.client.url: http://localhost:90/ str\n" ] } ], "source": [ - "print(conf.pretty(resolve=True))" + "conf.server.port = 90\n", + "# Primitive interpolation types are inherited from the referenced value\n", + "print(\"conf.client.server_port: \", conf.client.server_port, type(conf.client.server_port).__name__)\n", + "# Composite interpolation types are always string\n", + "print(\"conf.client.url: \", conf.client.url, type(conf.client.url).__name__)" ] }, { @@ -626,7 +628,12 @@ { "cell_type": "code", "execution_count": 20, - "metadata": {}, + "metadata": { + "pycharm": { + "name": "#%%\n" + }, + "scrolled": true + }, "outputs": [ { "name": "stdout", @@ -693,15 +700,15 @@ "output_type": "stream", "text": [ "user:\n", - " name: ${env:USER}\n", - " home: /home/${env:USER}\n", + " name: omry\n", + " home: /home/omry\n", "\n" ] } ], "source": [ "conf = OmegaConf.load('../source/env_interpolation.yaml')\n", - "print(conf.pretty())" + "print(OmegaConf.to_yaml(conf))" ] }, { @@ -718,15 +725,15 @@ "output_type": "stream", "text": [ "user:\n", - " name: omry\n", - " home: /home/omry\n", + " name: ${env:USER}\n", + " home: /home/${env:USER}\n", "\n" ] } ], "source": [ "conf = OmegaConf.load('../source/env_interpolation.yaml')\n", - "print(conf.pretty(resolve=True))" + "print(OmegaConf.to_yaml(conf, resolve=False))" ] }, { @@ -862,7 +869,7 @@ ], "source": [ "base_conf = OmegaConf.load('../source/example2.yaml')\n", - "print(base_conf.pretty())" + "print(OmegaConf.to_yaml(base_conf))" ] }, { @@ -886,7 +893,7 @@ ], "source": [ "second_conf = OmegaConf.load('../source/example3.yaml')\n", - "print(second_conf.pretty())" + "print(OmegaConf.to_yaml(second_conf))" ] }, { @@ -924,8 +931,15 @@ "sys.argv = ['program.py', 'server.port=82']\n", "# Merge with cli arguments\n", "conf.merge_with_cli()\n", - "print(conf.pretty())" + "print(OmegaConf.to_yaml(conf))" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -944,7 +958,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.3" + "version": "3.6.10" }, "pycharm": { "stem_cell": { diff --git a/docs/source/structured_config.rst b/docs/source/structured_config.rst index 659a8b1c5..18385a44e 100644 --- a/docs/source/structured_config.rst +++ b/docs/source/structured_config.rst @@ -66,7 +66,7 @@ fields during construction. >>> conf3 = OmegaConf.structured( ... SimpleTypes(num=20, ... height=Height.TALL)) - >>> print(conf3.pretty()) + >>> print(OmegaConf.to_yaml(conf3)) num: 20 pi: 3.1415 is_awesome: true @@ -176,7 +176,7 @@ Structured configs can be nested. ... manager: User = User(name="manager", height=Height.TALL) >>> conf : Group = OmegaConf.structured(Group) - >>> print(conf.pretty()) + >>> print(OmegaConf.to_yaml(conf)) name: ??? admin: name: ??? diff --git a/docs/source/usage.rst b/docs/source/usage.rst index 577278531..1e27d42ad 100644 --- a/docs/source/usage.rst +++ b/docs/source/usage.rst @@ -30,7 +30,7 @@ Empty >>> from omegaconf import OmegaConf >>> conf = OmegaConf.create() - >>> print(conf.pretty()) + >>> print(OmegaConf.to_yaml(conf)) {} @@ -40,7 +40,7 @@ From a dictionary .. doctest:: >>> conf = OmegaConf.create({"k" : "v", "list" : [1, {"a": "1", "b": "2"}]}) - >>> print(conf.pretty()) + >>> print(OmegaConf.to_yaml(conf)) k: v list: - 1 @@ -54,7 +54,7 @@ From a list .. doctest:: >>> conf = OmegaConf.create([1, {"a":10, "b": {"a":10}}]) - >>> print(conf.pretty()) + >>> print(OmegaConf.to_yaml(conf)) - 1 - a: 10 b: @@ -70,7 +70,7 @@ From a yaml file >>> conf = OmegaConf.load('source/example.yaml') >>> # Output is identical to the yaml file - >>> print(conf.pretty()) + >>> print(OmegaConf.to_yaml(conf)) server: port: 80 log: @@ -95,7 +95,7 @@ From a yaml string ... - item2 ... """ >>> conf = OmegaConf.create(s) - >>> print(conf.pretty()) + >>> print(OmegaConf.to_yaml(conf)) a: b b: c list: @@ -110,7 +110,7 @@ From a dot-list >>> dot_list = ["a.aa.aaa=1", "a.aa.bbb=2", "a.bb.aaa=3", "a.bb.bbb=4"] >>> conf = OmegaConf.from_dotlist(dot_list) - >>> print(conf.pretty()) + >>> print(OmegaConf.to_yaml(conf)) a: aa: aaa: 1 @@ -130,7 +130,7 @@ To parse the content of sys.arg: >>> # Simulating command line arguments >>> sys.argv = ['your-program.py', 'server.port=82', 'log.file=log2.txt'] >>> conf = OmegaConf.from_cli() - >>> print(conf.pretty()) + >>> print(OmegaConf.to_yaml(conf)) server: port: 82 log: @@ -153,7 +153,7 @@ See :doc:`structured_config` for more details, or keep reading for a minimal exa ... host: str = "localhost" >>> # For strict typing purposes, prefer OmegaConf.structured() when creating structured configs >>> conf = OmegaConf.structured(MyConfig) - >>> print(conf.pretty()) + >>> print(OmegaConf.to_yaml(conf)) port: 80 host: localhost @@ -163,7 +163,7 @@ You can use an object to initialize the config as well: .. doctest:: >>> conf = OmegaConf.structured(MyConfig(port=443)) - >>> print(conf.pretty()) + >>> print(OmegaConf.to_yaml(conf)) port: 443 host: localhost @@ -427,7 +427,7 @@ Note how the port changes to 82, and how the users lists are combined. >>> >>> # merge them all >>> conf = OmegaConf.merge(base_conf, second_conf, cli_conf) - >>> print(conf.pretty()) + >>> print(OmegaConf.to_yaml(conf)) server: port: 82 users: @@ -589,13 +589,13 @@ Creates a copy of a DictConfig that contains only specific keys. .. doctest:: loaded >>> conf = OmegaConf.create({"a": {"b": 10}, "c":20}) - >>> print(conf.pretty()) + >>> print(OmegaConf.to_yaml(conf)) a: b: 10 c: 20 >>> c = OmegaConf.masked_copy(conf, ["a"]) - >>> print(c.pretty()) + >>> print(OmegaConf.to_yaml(c)) a: b: 10 diff --git a/news/263.removal b/news/263.removal new file mode 100644 index 000000000..a89569d50 --- /dev/null +++ b/news/263.removal @@ -0,0 +1 @@ +cfg.pretty() is deprecated in favor of OmegaConf.to_yaml(config). Resolve parameter now defaults to True. diff --git a/omegaconf/basecontainer.py b/omegaconf/basecontainer.py index 9a5ba2076..e66faf381 100644 --- a/omegaconf/basecontainer.py +++ b/omegaconf/basecontainer.py @@ -13,7 +13,6 @@ _get_value, _is_interpolation, _resolve_optional, - get_omega_conf_dumper, get_ref_type, get_value_kind, get_yaml_loader, @@ -216,24 +215,19 @@ def convert(val: Node) -> Any: assert False def pretty(self, resolve: bool = False, sort_keys: bool = False) -> str: - """ - returns a yaml dump of this config object. - :param resolve: if True, will return a string with the interpolations resolved, otherwise - interpolations are preserved - :param sort_keys: If True, will print dict keys in sorted order. default False. - :return: A string containing the yaml representation. - """ from omegaconf import OmegaConf - container = OmegaConf.to_container(self, resolve=resolve, enum_to_str=True) - return yaml.dump( # type: ignore - container, - default_flow_style=False, - allow_unicode=True, - sort_keys=sort_keys, - Dumper=get_omega_conf_dumper(), + warnings.warn( + """ + pretty() is deprecated and will be removed in a future version. + Use OmegaConf.to_yaml. Please note that the default value for + resolve has changed to True. + """, + category=UserWarning, ) + return OmegaConf.to_yaml(self, resolve=resolve, sort_keys=sort_keys) + @staticmethod def _map_merge(dest: "BaseContainer", src: "BaseContainer") -> None: """merge src into dest and return a new copy, does not modified input""" diff --git a/omegaconf/omegaconf.py b/omegaconf/omegaconf.py index 780527e46..9819eb66b 100644 --- a/omegaconf/omegaconf.py +++ b/omegaconf/omegaconf.py @@ -34,6 +34,7 @@ format_and_raise, get_dict_key_value_types, get_list_element_type, + get_omega_conf_dumper, get_type_of, is_attr_class, is_dataclass, @@ -273,7 +274,7 @@ def save( """ if is_dataclass(config) or is_attr_class(config): config = OmegaConf.create(config) - data = config.pretty(resolve=resolve) + data = OmegaConf.to_yaml(config, resolve=resolve) if isinstance(f, (str, pathlib.Path)): with io.open(os.path.abspath(f), "w", encoding="utf-8") as file: file.write(data) @@ -568,6 +569,26 @@ def update(cfg: Container, key: str, value: Any = None) -> None: idx = int(last) root[idx] = value + @staticmethod + def to_yaml( + cfg: Container, *, resolve: bool = True, sort_keys: bool = False + ) -> str: + """ + returns a yaml dump of this config object. + :param resolve: if True, will return a string with the interpolations resolved, otherwise + interpolations are preserved + :param sort_keys: If True, will print dict keys in sorted order. default False. + :return: A string containing the yaml representation. + """ + container = OmegaConf.to_container(cfg, resolve=resolve, enum_to_str=True) + return yaml.dump( # type: ignore + container, + default_flow_style=False, + allow_unicode=True, + sort_keys=sort_keys, + Dumper=get_omega_conf_dumper(), + ) + # register all default resolvers register_default_resolvers() diff --git a/tests/examples/test_dataclass_example.py b/tests/examples/test_dataclass_example.py index b831a5ebc..7711600d3 100644 --- a/tests/examples/test_dataclass_example.py +++ b/tests/examples/test_dataclass_example.py @@ -159,7 +159,7 @@ def test_nesting() -> None: name: manager height: TALL """ - assert conf.pretty() == expected + assert OmegaConf.to_yaml(conf) == expected # you can assign a different object of the same type conf.admin = User(name="omry", height=Height.TALL) diff --git a/tests/test_basic_ops_dict.py b/tests/test_basic_ops_dict.py index f0025ca14..ba3fd4a1b 100644 --- a/tests/test_basic_ops_dict.py +++ b/tests/test_basic_ops_dict.py @@ -119,52 +119,6 @@ def test_subscript_set_with_dot_warning_suppressed(recwarn: Any, mocker: Any) -> assert len(recwarn) == 0 -def test_pretty_dict() -> None: - c = OmegaConf.create(dict(hello="world", list=[1, 2])) - expected = """hello: world -list: -- 1 -- 2 -""" - assert expected == c.pretty() - assert OmegaConf.create(c.pretty()) == c - - -def test_pretty_sort_keys() -> None: - c = OmegaConf.create({"b": 2, "a": 1}) - # keys are not sorted by default - assert c.pretty() == "b: 2\na: 1\n" - c = OmegaConf.create({"b": 2, "a": 1}) - assert c.pretty(sort_keys=True) == "a: 1\nb: 2\n" - - -def test_pretty_dict_unicode() -> None: - c = OmegaConf.create(dict(你好="世界", list=[1, 2])) - expected = """你好: 世界 -list: -- 1 -- 2 -""" - assert expected == c.pretty() - assert OmegaConf.create(c.pretty()) == c - - -def test_pretty_strings_float() -> None: - c = OmegaConf.create({"b": "10e2", "a": "1.0", "c": 1.0}) - assert c.pretty() == "b: '10e2'\na: '1.0'\nc: 1.0\n" - - -def test_pretty_string_boolean() -> None: - for t in _utils.YAML_BOOL_TYPES: - c = OmegaConf.create({"b": t, "a": 1}) - assert c.pretty() == "b: '%s'\na: 1\n" % t - - -def test_pretty_string_int() -> None: - c = OmegaConf.create({"b": "1", "a": 1}) - assert c.pretty() == "b: '1'\na: 1\n" - - def test_default_value() -> None: c = OmegaConf.create() assert c.missing_key or "a default value" == "a default value" @@ -522,25 +476,6 @@ def test_assign_dict_in_dict() -> None: assert isinstance(c.foo, DictConfig) -def test_pretty_without_resolve() -> None: - c = OmegaConf.create(dict(a1="${ref}", ref="bar")) - # without resolve, references are preserved - c2 = OmegaConf.create(c.pretty(resolve=False)) - assert isinstance(c2, DictConfig) - assert c2.a1 == "bar" - c2.ref = "changed" - assert c2.a1 == "changed" - - -def test_pretty_with_resolve() -> None: - c = OmegaConf.create(dict(a1="${ref}", ref="bar")) - c2 = OmegaConf.create(c.pretty(resolve=True)) - assert isinstance(c2, DictConfig) - assert c2.a1 == "bar" - c2.ref = "changed" - assert c2.a1 == "bar" - - def test_instantiate_config_fails() -> None: with pytest.raises(TypeError): BaseContainer() # type: ignore diff --git a/tests/test_basic_ops_list.py b/tests/test_basic_ops_list.py index 3f8ae1037..9e0f875f1 100644 --- a/tests/test_basic_ops_list.py +++ b/tests/test_basic_ops_list.py @@ -4,7 +4,7 @@ import pytest -from omegaconf import AnyNode, ListConfig, OmegaConf, _utils +from omegaconf import AnyNode, ListConfig, OmegaConf from omegaconf.errors import ( ConfigKeyError, ConfigTypeError, @@ -30,49 +30,6 @@ def test_list_of_dicts() -> None: assert c[1].key2 == "value2" -def test_pretty_list() -> None: - c = OmegaConf.create(["item1", "item2", dict(key3="value3")]) - expected = """- item1 -- item2 -- key3: value3 -""" - assert expected == c.pretty() - assert OmegaConf.create(c.pretty()) == c - - -def test_pretty_list_unicode() -> None: - c = OmegaConf.create(["item一", "item二", dict(key三="value三")]) - expected = """- item一 -- item二 -- key三: value三 -""" - assert expected == c.pretty() - assert OmegaConf.create(c.pretty()) == c - - -def test_pretty_strings_float() -> None: - c = OmegaConf.create(["10e2", "1.0", 1.0]) - expected = """- '10e2' -- '1.0' -- 1.0 -""" - assert c.pretty() == expected - - -def test_pretty_string_boolean() -> None: - for t in _utils.YAML_BOOL_TYPES: - print(t) - c = OmegaConf.create([t, 1]) - expected = "- '%s'\n- 1\n" % t - assert c.pretty() == expected - - -def test_pretty_string_int() -> None: - c = OmegaConf.create(["1", 1]) - expected = "- '1'\n- 1\n" - assert c.pretty() == expected - - def test_list_get_with_default() -> None: c = OmegaConf.create([None, "???", "found"]) assert c.get(0, "default_value") == "default_value" @@ -230,25 +187,6 @@ def test_list_append() -> None: validate_list_keys(c) -def test_pretty_without_resolve() -> None: - c = OmegaConf.create([100, "${0}"]) - # without resolve, references are preserved - yaml_str = c.pretty(resolve=False) - c2 = OmegaConf.create(yaml_str) - assert isinstance(c2, ListConfig) - c2[0] = 1000 - assert c2[1] == 1000 - - -def test_pretty_with_resolve() -> None: - c = OmegaConf.create([100, "${0}"]) - # with resolve, references are not preserved. - c2 = OmegaConf.create(c.pretty(resolve=True)) - assert isinstance(c2, ListConfig) - c2[0] = 1000 - assert c[1] == 100 - - @pytest.mark.parametrize( # type: ignore "index, expected", [(slice(1, 3), [11, 12]), (slice(0, 3, 2), [10, 12]), (-1, 13)] ) diff --git a/tests/test_nodes.py b/tests/test_nodes.py index 760666552..18facc33e 100644 --- a/tests/test_nodes.py +++ b/tests/test_nodes.py @@ -353,22 +353,6 @@ def test_legal_assignment_enum( node_type(enum_type) -def test_pretty_with_enum() -> None: - cfg = OmegaConf.create() - assert isinstance(cfg, DictConfig) - cfg.foo = EnumNode(Enum1) - cfg.foo = Enum1.FOO - - expected = """foo: FOO -""" - s = cfg.pretty() - assert s == expected - assert ( - OmegaConf.merge({"foo": EnumNode(Enum1, value="???")}, OmegaConf.create(s)) - == cfg - ) - - class DummyEnum(Enum): FOO = 1 diff --git a/tests/test_to_yaml.py b/tests/test_to_yaml.py new file mode 100644 index 000000000..4b3ae96f0 --- /dev/null +++ b/tests/test_to_yaml.py @@ -0,0 +1,139 @@ +import re +from typing import Any + +import pytest + +from omegaconf import DictConfig, EnumNode, ListConfig, OmegaConf, _utils + +from . import Enum1 + + +@pytest.mark.parametrize( # type: ignore + "input_, expected", + [ + (["item1", "item2", dict(key3="value3")], "- item1\n- item2\n- key3: value3\n"), + (dict(hello="world", list=[1, 2]), "hello: world\nlist:\n- 1\n- 2\n"), + ], +) +def test_to_yaml(input_: Any, expected: str) -> None: + c = OmegaConf.create(input_) + assert expected == OmegaConf.to_yaml(c) + assert OmegaConf.create(OmegaConf.to_yaml(c)) == c + + +@pytest.mark.parametrize( # type: ignore + "input_, expected", + [ + (["item一", "item二", dict(key三="value三")], "- item一\n- item二\n- key三: value三\n"), + (dict(你好="世界", list=[1, 2]), "你好: 世界\nlist:\n- 1\n- 2\n"), + ], +) +def test_to_yaml_unicode(input_: Any, expected: str) -> None: + c = OmegaConf.create(input_) + assert expected == OmegaConf.to_yaml(c) + assert OmegaConf.create(OmegaConf.to_yaml(c)) == c + + +@pytest.mark.parametrize( # type: ignore + "input_, expected, type_", + [ + (["1", 1], "- '1'\n- 1\n", int), + (["10e2", "1.0", 1.0], "- '10e2'\n- '1.0'\n- 1.0\n", float), + (_utils.YAML_BOOL_TYPES, None, bool), + ], +) +def test_to_yaml_string_primitive_types_list( + input_: Any, expected: str, type_: type +) -> None: + if type_ == bool: + for t in input_: + c = OmegaConf.create([t, 1]) + expected = "- '%s'\n- 1\n" % t + assert OmegaConf.to_yaml(c) == expected + + else: + c = OmegaConf.create(input_) + assert OmegaConf.to_yaml(c) == expected + + +@pytest.mark.parametrize( # type: ignore + "input_, expected, type_", + [ + ({"b": "1", "a": 1}, "b: '1'\na: 1\n", int), + ({"b": "10e2", "a": "1.0", "c": 1.0}, "b: '10e2'\na: '1.0'\nc: 1.0\n", float), + (_utils.YAML_BOOL_TYPES, None, bool), + ], +) +def test_to_yaml_string_primitive_types_dict( + input_: Any, expected: str, type_: type +) -> None: + if type_ == bool: + for t in input_: + c = OmegaConf.create({"b": t, "a": 1}) + assert OmegaConf.to_yaml(c) == "b: '%s'\na: 1\n" % t + else: + c = OmegaConf.create(input_) + assert OmegaConf.to_yaml(c) == expected + + +@pytest.mark.parametrize( # type: ignore + "input_, resolve, expected", + [ + (dict(a1="${ref}", ref="bar"), True, "bar"), + (dict(a1="${ref}", ref="bar"), False, "changed"), + ([100, "${0}"], True, 100), + ([100, "${0}"], False, 1000), + ], +) +def test_to_yaml_resolve(input_: Any, resolve: bool, expected: int) -> None: + c = OmegaConf.create(input_) + # without resolve, references are preserved + yaml_str = OmegaConf.to_yaml(c, resolve=resolve) + c2 = OmegaConf.create(yaml_str) + assert isinstance(c2, ListConfig) or isinstance(c2, DictConfig) + if isinstance(c2, DictConfig): + assert c2.a1 == "bar" + c2.ref = "changed" + assert c2.a1 == expected + else: + c2[0] = 1000 + assert c2[1] == expected + + +def test_to_yaml_sort_keys() -> None: + c = OmegaConf.create({"b": 2, "a": 1}) + # keys are not sorted by default + assert OmegaConf.to_yaml(c) == "b: 2\na: 1\n" + c = OmegaConf.create({"b": 2, "a": 1}) + assert OmegaConf.to_yaml(c, sort_keys=True) == "a: 1\nb: 2\n" + + +def test_to_yaml_with_enum() -> None: + cfg = OmegaConf.create() + assert isinstance(cfg, DictConfig) + cfg.foo = EnumNode(Enum1) + cfg.foo = Enum1.FOO + + expected = """foo: FOO +""" + s = OmegaConf.to_yaml(cfg) + assert s == expected + assert ( + OmegaConf.merge({"foo": EnumNode(Enum1, value="???")}, OmegaConf.create(s)) + == cfg + ) + + +def test_pretty_deprecated() -> None: + c = OmegaConf.create({"foo": "bar"}) + with pytest.warns( + expected_warning=UserWarning, + match=re.escape( + """ + pretty() is deprecated and will be removed in a future version. + Use OmegaConf.to_yaml. Please note that the default value for + resolve has changed to True. + """, + ), + ): + assert c.pretty() == "foo: bar\n"