From 73d4d22287ef3955fb8cd02d589b15dc4dbff8a9 Mon Sep 17 00:00:00 2001
From: Alexander Schlemmer <alexander@mail-schlemmer.de>
Date: Fri, 20 May 2022 15:39:46 +0200
Subject: [PATCH] ENH: enhanced macro format

---
 src/caoscrawler/macros/__init__.py          |  2 +-
 src/caoscrawler/macros/macro_yaml_object.py | 51 +++++++++++++--------
 unittests/test_macros.py                    | 27 +++++------
 3 files changed, 43 insertions(+), 37 deletions(-)

diff --git a/src/caoscrawler/macros/__init__.py b/src/caoscrawler/macros/__init__.py
index 3b01d811..0acfb176 100644
--- a/src/caoscrawler/macros/__init__.py
+++ b/src/caoscrawler/macros/__init__.py
@@ -1 +1 @@
-from .macro_yaml_object import defmacro_constructor, macro_constructor, multimacro_constructor
+from .macro_yaml_object import defmacro_constructor, macro_constructor
diff --git a/src/caoscrawler/macros/macro_yaml_object.py b/src/caoscrawler/macros/macro_yaml_object.py
index 056152c9..46e8affe 100644
--- a/src/caoscrawler/macros/macro_yaml_object.py
+++ b/src/caoscrawler/macros/macro_yaml_object.py
@@ -117,26 +117,37 @@ def macro_constructor(loader, node):
     It can be registered in pyaml using:
     yaml.SafeLoader.add_constructor("!macro", macro_constructor)
     """
+    res = dict()
     value = loader.construct_mapping(node, deep=True)
-    name = value["name"]
-    macro = macro_store[name]
-    params = deepcopy(macro.params)
-    if "params" in value:
-        params.update(value["params"])
-    definition = deepcopy(macro.definition)
+    for name, params_setter in value.items():
+        if name in macro_store:
+            # If params_setter is a list, run this for every element:
+            if params_setter is not None and isinstance(params_setter, list):
+                for el in params_setter:
+                    macro = macro_store[name]
+                    params = deepcopy(macro.params)
+                    if el is not None:
+                        if isinstance(el, dict):
+                            params.update(el)
+                        else:
+                            raise RuntimeError("params type not supported")
+                    else:
+                        raise RuntimeError("params type must not be None")
+                    definition = substitute_dict(macro.definition, params)
+                    res.update(definition)
+            else:
+                # This is just a single macro:
+                macro = macro_store[name]
+                params = deepcopy(macro.params)
+                if params_setter is not None:
+                    if isinstance(params_setter, dict):
+                        params.update(params_setter)
+                    else:
+                        raise RuntimeError("params type not supported")
+                definition = substitute_dict(macro.definition, params)
+                res.update(definition)
+        else:
+            # If there is no macro with that name, just keep that node:
+            res[name] = params_setter
     
-    return substitute_dict(definition, params)
-
-def multimacro_constructor(loader, node):
-    """
-    Function that can be used to chain macros for complex definitions of dictionaries.
-
-    It can be registered in pyaml using:
-    yaml.SafeLoader.add_constructor("!multimacro", multimacro_constructor)
-    """
-
-    res = dict()
-    for val in node.value:
-        res.update(macro_constructor(loader, val))
-
     return res
diff --git a/unittests/test_macros.py b/unittests/test_macros.py
index dfb4bd0a..048f0527 100644
--- a/unittests/test_macros.py
+++ b/unittests/test_macros.py
@@ -22,9 +22,7 @@
 # ** end header
 #
 
-from caoscrawler.macros import (defmacro_constructor,
-                                macro_constructor,
-                                multimacro_constructor)
+from caoscrawler.macros import defmacro_constructor, macro_constructor
 from caoscrawler.macros.macro_yaml_object import macro_store
 import yaml
 import pytest
@@ -33,7 +31,6 @@ import pytest
 def register_macros():
     yaml.SafeLoader.add_constructor("!defmacro", defmacro_constructor)
     yaml.SafeLoader.add_constructor("!macro", macro_constructor)
-    yaml.SafeLoader.add_constructor("!multimacro", multimacro_constructor)
 
 @pytest.fixture
 def macro_store_reset():
@@ -55,8 +52,7 @@ defs:
 
 testnode:
   obl: !macro
-    name: test
-    params:
+    test:
       a: 4
       b: yea
 """, Loader=yaml.SafeLoader)
@@ -82,8 +78,7 @@ defs:
 
 testnode:
   obl: !macro
-    name: test
-    params:
+    test:
       a: 4
       b: yea
 """, Loader=yaml.SafeLoader)
@@ -108,9 +103,9 @@ defs:
     replaced3: ok
 
 testnode:
-    obl: !multimacro
-    - name: test_one
-    - name: test_two
+    obl: !macro
+      test_one:
+      test_two:
 """, Loader=yaml.SafeLoader)
     print(yaml.dump(dat))
     assert dat["testnode"]["obl"]["replaced1"] == "ok"
@@ -136,9 +131,9 @@ defs:
     replaced2: ok
     replaced3: ok
 
-testnode: !multimacro
-    - name: test_one
-    - name: test_two
+testnode: !macro
+  test_one:
+  test_two:
 """, Loader=yaml.SafeLoader)
     assert dat["testnode"]["replaced1"] == "ok"
     assert dat["testnode"]["replaced2"] == "ok"
@@ -169,8 +164,8 @@ defs:
       d: $testvar_list
 
 testnode:
-    obl: !macro
-      name: test
+  obl: !macro
+    test:
 """, Loader=yaml.SafeLoader)
     print(yaml.dump(dat))
     assert dat["testnode"]["obl"]["replaced1"]["c"]["t1"] == "a"
-- 
GitLab