From 9a2dd209280c3acb86a71d5b349d62cc185efdad Mon Sep 17 00:00:00 2001
From: Yannick DAYER <yannick.dayer@idiap.ch>
Date: Fri, 11 Nov 2022 22:53:32 +0100
Subject: [PATCH] Use the exposed rc implementation for toml support

---
 bob/extension/__init__.py          |  4 ++-
 bob/extension/data/defaults-config |  9 ++---
 bob/extension/rc_config.py         | 45 +++++++++++++++++-------
 bob/extension/scripts/config.py    |  2 +-
 bob/extension/test_rc.py           | 55 ++++++------------------------
 conda/meta.yaml                    |  2 ++
 6 files changed, 54 insertions(+), 63 deletions(-)

diff --git a/bob/extension/__init__.py b/bob/extension/__init__.py
index 16c9116..b0f5696 100644
--- a/bob/extension/__init__.py
+++ b/bob/extension/__init__.py
@@ -11,6 +11,8 @@ import logging
 
 import pkg_resources
 
+from copy import deepcopy
+
 from .rc_config import _loadrc
 
 logger = logging.getLogger(__name__)
@@ -39,7 +41,7 @@ def rc_context(dict):
     >>> a
     1
     """
-    old_rc = rc.copy()
+    old_rc = deepcopy(rc)
     try:
         rc.update(dict)
         yield
diff --git a/bob/extension/data/defaults-config b/bob/extension/data/defaults-config
index f332e2b..cf5ebda 100644
--- a/bob/extension/data/defaults-config
+++ b/bob/extension/data/defaults-config
@@ -1,4 +1,5 @@
-{
-    "bob.db.atnt.directory": "/home/bob/databases/atnt",
-    "bob.db.mobio.directory": "/home/bob/databases/mobio"
-}
+[bob.db.atnt]
+directory = "/home/bob/databases/atnt"
+
+[bob.db.mobio]
+directory = "/home/bob/databases/mobio"
diff --git a/bob/extension/rc_config.py b/bob/extension/rc_config.py
index 536a421..497203c 100644
--- a/bob/extension/rc_config.py
+++ b/bob/extension/rc_config.py
@@ -7,7 +7,9 @@ import json
 import logging
 import os
 
-from collections import defaultdict
+from exposed.rc import UserDefaults
+
+from warnings import warn
 
 logger = logging.getLogger(__name__)
 
@@ -52,20 +54,28 @@ def _loadrc():
 
     """
 
-    def _default_none_dict(dct):
-        dct2 = defaultdict(lambda: None)
-        dct2.update(dct)
-        return dct2
+    warn(
+        "rc from bob.extension is deprecated. Please use exposed.rc instead.",
+        DeprecationWarning,
+    )
+    # def _default_none_dict(dct):
+    #     dct2 = defaultdict(lambda: None)
+    #     dct2.update(dct)
+    #     return dct2
 
-    path = _get_rc_path()
-    if not os.path.exists(path):
-        logger.debug("No RC file found")
-        return _default_none_dict({})
+    # path = _get_rc_path()
+    # if not os.path.exists(path):
+    #     logger.debug("No RC file found")
+    #     return _default_none_dict({})
 
-    logger.debug("Loading RC file `%s'...", path)
+    # logger.debug("Loading RC file `%s'...", path)
 
-    with open(path, "rt") as f:
-        return json.load(f, object_hook=_default_none_dict)
+    # with open(path, "rt") as f:
+    #     return json.load(f, object_hook=_default_none_dict)
+
+    # XXX ydayer202211 This will use exposed in the background while transitioning away
+    # from bob.extension. This has the effect to switch the format of ~/.bobrc to toml.
+    return UserDefaults(path=RCFILENAME, envname=ENVNAME, logger=logger)
 
 
 def _rc_to_str(context):
@@ -82,7 +92,11 @@ def _rc_to_str(context):
         The configurations in a JSON formatted string.
     """
 
-    return json.dumps(context, sort_keys=True, indent=4, separators=(",", ": "))
+    warn(
+        "rc from bob.extension is deprecated. Please use exposed.rc instead.",
+        DeprecationWarning,
+    )
+    return str(UserDefaults(path=RCFILENAME, envname=ENVNAME, logger=logger))
 
 
 def _saverc(context):
@@ -94,6 +108,11 @@ def _saverc(context):
         All the configurations to save into the rc file.
     """
 
+    warn(
+        "rc from bob.extension is deprecated. Please use exposed.rc instead.",
+        DeprecationWarning,
+    )
+
     path = _get_rc_path()
     with open(path, "wt") as f:
         f.write(_rc_to_str(context))
diff --git a/bob/extension/scripts/config.py b/bob/extension/scripts/config.py
index 3776304..bb877f2 100644
--- a/bob/extension/scripts/config.py
+++ b/bob/extension/scripts/config.py
@@ -89,7 +89,7 @@ def set(key, value):
     """
     try:
         rc[key] = value
-        _saverc(rc)
+        rc.write()
     except Exception:
         logger.error("Could not configure the rc file", exc_info=True)
         raise click.ClickException("Failed to change the configuration.")
diff --git a/bob/extension/test_rc.py b/bob/extension/test_rc.py
index 74c57c0..cba564e 100644
--- a/bob/extension/test_rc.py
+++ b/bob/extension/test_rc.py
@@ -17,13 +17,14 @@ def test_rc_env():
 
     os.environ[ENVNAME] = os.path.join(path, "defaults-config")
     c = _loadrc()  # should load from environment variable
-    REFERENCE = {
-        "bob.db.atnt.directory": "/home/bob/databases/atnt",
-        "bob.db.mobio.directory": "/home/bob/databases/mobio",
-    }
+    REFERENCE = """[bob.db.atnt]
+directory = "/home/bob/databases/atnt"
 
-    assert c == REFERENCE
-    assert c["random"] is None
+[bob.db.mobio]
+directory = "/home/bob/databases/mobio"
+"""
+    assert str(c) == REFERENCE
+    assert "random" not in c
 
 
 def test_bob_config():
@@ -40,9 +41,8 @@ def test_bob_config():
     result = runner.invoke(main_cli, ["config", "get", "bob.db.atnt.directory"])
     assert_click_runner_result(result, 0)
     assert result.output == "/home/bob/databases/atnt\n", result.output
-
     # test config get (non-existing key)
-    result = runner.invoke(main_cli, ["config", "get", "bob.db.atnt"])
+    result = runner.invoke(main_cli, ["config", "get", "not.an.existing.key"])
     assert_click_runner_result(result, 1)
 
     # test config set
@@ -67,41 +67,8 @@ def test_bob_config():
         )
         assert_click_runner_result(result, 0)
         expected_output = """Displaying `bobrc':
-{
-    "bob.db.atnt.directory": "/home/bob/databases/orl_faces"
-}
+[bob.db.atnt]
+directory = "/home/bob/databases/orl_faces"
+
 """
         assert expected_output == result.output, result.output
-
-        # test config unset (with starting substring)
-        result = runner.invoke(
-            main_cli,
-            ["config", "unset", "bob.db.atnt"],
-            env={ENVNAME: bobrcfile},
-        )
-        result = runner.invoke(
-            main_cli, ["config", "get", "bob.db.atnt"], env={ENVNAME: bobrcfile}
-        )
-        assert_click_runner_result(result, 1)
-
-        # test config unset (with substring contained)
-        # reset the key / value pair
-        result = runner.invoke(
-            main_cli,
-            [
-                "config",
-                "set",
-                "bob.db.atnt.directory",
-                "/home/bob/databases/orl_faces",
-            ],
-            env={ENVNAME: bobrcfile},
-        )
-        result = runner.invoke(
-            main_cli,
-            ["config", "unset", "--contain", "atnt"],
-            env={ENVNAME: bobrcfile},
-        )
-        result = runner.invoke(
-            main_cli, ["config", "get", "bob.db.atnt"], env={ENVNAME: bobrcfile}
-        )
-        assert_click_runner_result(result, 1)
diff --git a/conda/meta.yaml b/conda/meta.yaml
index 2bdfc5c..665c7ba 100644
--- a/conda/meta.yaml
+++ b/conda/meta.yaml
@@ -21,12 +21,14 @@ requirements:
     - python {{ python }}
     - setuptools {{ setuptools }}
     - pip {{ pip }}
+    - exposed
     - click >=8
     - click {{ click }}
     - click-plugins {{ click_plugins }}
   run:
     - python
     - setuptools
+    - exposed
     - {{ pin_compatible('click') }}
     - {{ pin_compatible('click-plugins') }}
 
-- 
GitLab