Repository: Materials-Consortia/optimade-python-tools
Pull request #137 (2020-01-16 11:03:40)

Fix `load_from_json`
This function did not work properly.

Add test file for config.py, for now only with a simple test to run `load_from_json()`.

Feel free to add more tests to `test_config.py` either in this PR or later.


Patch:
diff --git a/optimade/server/config.py b/optimade/server/config.py
index de1a38aa..ac75fcaa 100644
--- a/optimade/server/config.py
+++ b/optimade/server/config.py
@@ -146,7 +146,7 @@ class ServerConfig(Config):
         self.implementation = {}
         for field in Implementation.schema()["properties"]:
             value_config = config.get("IMPLEMENTATION", field, fallback=None)
-            value_default = self._DEFAULTS(f"implementation")[field]
+            value_default = self._DEFAULTS("implementation")[field]
             if value_config is not None:
                 self.implementation[field] = value_config
             elif value_default is not None:
@@ -191,18 +191,18 @@ class ServerConfig(Config):
             setattr(
                 self,
                 f"{endpoint}_collection",
-                config.get(f"{endpoint}_collection"),
-                getattr(self._DEFAULTS(f"{endpoint}_collection")),
+                config.get(
+                    f"{endpoint}_collection", self._DEFAULTS(f"{endpoint}_collection")
+                ),
             )
 
         self.page_limit = int(config.get("page_limit", self._DEFAULTS("page_limit")))
-        self.version = config.get("api_version", self._DEFAULTS("api_version"))
         self.default_db = config.get("default_db", self._DEFAULTS("default_db"))
 
         # This is done in this way, since each field is OPTIONAL
         self.implementation = config.get("implementation", {})
         for field in Implementation.schema()["properties"]:
-            value_default = self._DEFAULTS(f"implementation.{field}")
+            value_default = self._DEFAULTS("implementation")[field]
             if field in self.implementation:
                 # Keep the config value
                 pass
@@ -210,9 +210,11 @@ class ServerConfig(Config):
                 self.implementation[field] = value_default
 
         self.provider = config.get("provider", self._DEFAULTS("provider"))
-        self.provider_fields = set(
-            config.get("provider_fields", self._DEFAULTS("provider_fields"))
-        )
+        self.provider_fields = {}
+        for endpoint in {"structures", "references"}:
+            self.provider_fields[endpoint] = set(
+                config.get("provider_fields", {}).get(endpoint, [])
+            )
 
 
 CONFIG = ServerConfig()


Test patch:
diff --git a/tests/server/config_test.ini b/tests/server/config_test.ini
new file mode 100644
index 00000000..17ece366
--- /dev/null
+++ b/tests/server/config_test.ini
@@ -0,0 +1,25 @@
+[BACKEND]
+USE_REAL_MONGO = no
+MONGO_DATABASE = optimade
+LINKS_COLLECTION = links
+REFERENCES_COLLECTION = references
+STRUCTURES_COLLECTION = structures
+
+[SERVER]
+PAGE_LIMIT = 500
+DEFAULT_DB = test_server
+
+[IMPLEMENTATION]
+name = Example implementation
+source_url = https://github.com/Materials-Consortia/optimade-python-tools
+
+[PROVIDER]
+prefix = _exmpl_
+name = Example provider
+description = Provider used for examples, not to be assigned to a real database
+homepage = http://example.com
+index_base_url = http://localhost:5001/index/optimade
+
+[structures]
+band_gap :
+_mp_chemsys :
diff --git a/tests/server/config_test.json b/tests/server/config_test.json
new file mode 100644
index 00000000..a1ab885c
--- /dev/null
+++ b/tests/server/config_test.json
@@ -0,0 +1,26 @@
+{
+    "use_real_mongo": false,
+    "mongo_database": "optimade",
+    "links_collection": "links",
+    "references_collection": "references",
+    "structures_collection": "structures",
+    "page_limit": 500,
+    "default_db": "test_server",
+    "implementation": {
+        "name": "Example implementation",
+        "source_url": "https://github.com/Materials-Consortia/optimade-python-tools"
+    },
+    "provider": {
+        "prefix": "_exmpl_",
+        "name": "Example provider",
+        "description": "Provider used for examples, not to be assigned to a real database",
+        "homepage": "http://example.com",
+        "index_base_url": "http://localhost:5001/index/optimade"
+    },
+    "provider_fields": {
+        "structures": [
+            "band_gap",
+            "_mp_chemsys"
+        ]
+    }
+}
diff --git a/tests/server/server_test_ini.cfg b/tests/server/server_test_ini.cfg
new file mode 100644
index 00000000..b487c807
--- /dev/null
+++ b/tests/server/server_test_ini.cfg
@@ -0,0 +1,3 @@
+[optimadeconfig]
+CONFIG = ./config_test.ini
+# INDEX_LINKS = ./index_links.json
diff --git a/tests/server/server_test_json.cfg b/tests/server/server_test_json.cfg
new file mode 100644
index 00000000..3e77e7a5
--- /dev/null
+++ b/tests/server/server_test_json.cfg
@@ -0,0 +1,3 @@
+[optimadeconfig]
+CONFIG = ./config_test.json
+# INDEX_LINKS = ./index_links.json
diff --git a/tests/server/test_config.py b/tests/server/test_config.py
new file mode 100644
index 00000000..3efc30a1
--- /dev/null
+++ b/tests/server/test_config.py
@@ -0,0 +1,40 @@
+# pylint: disable=import-outside-toplevel,protected-access,pointless-statement
+import unittest
+
+from pathlib import Path
+
+
+class LoadFromIniTest(unittest.TestCase):
+    """Test server.config.ServerConfig.load_from_ini"""
+
+    def test_config_ini(self):
+        """Invoke CONFIG using config_test.ini"""
+        from optimade.server.config import ServerConfig
+
+        CONFIG = ServerConfig(
+            server_cfg=Path(__file__).parent.joinpath("server_test_ini.cfg").resolve()
+        )
+
+        CONFIG.default_db  # Initiate CONFIG, running load_from_json()
+        # _path should now be updated with the correct path to the config json file:
+        self.assertEqual(
+            CONFIG._path, Path(__file__).parent.joinpath("config_test.ini").resolve()
+        )
+
+
+class LoadFromJsonTest(unittest.TestCase):
+    """Test server.config.ServerConfig.load_from_json"""
+
+    def test_config_json(self):
+        """Invoke CONFIG using config_test.json"""
+        from optimade.server.config import ServerConfig
+
+        CONFIG = ServerConfig(
+            server_cfg=Path(__file__).parent.joinpath("server_test_json.cfg").resolve()
+        )
+
+        CONFIG.default_db  # Initiate CONFIG, running load_from_json()
+        # _path should now be updated with the correct path to the config json file:
+        self.assertEqual(
+            CONFIG._path, Path(__file__).parent.joinpath("config_test.json").resolve()
+        )