[rtems-central commit] items: Add enabled set to ItemCache

Sebastian Huber sebh at rtems.org
Tue May 9 13:45:26 UTC 2023


Module:    rtems-central
Branch:    master
Commit:    ff4111c6eaa464b5a634d41d49bc755641f00090
Changeset: http://git.rtems.org/rtems-central/commit/?id=ff4111c6eaa464b5a634d41d49bc755641f00090

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri May  5 14:41:18 2023 +0200

items: Add enabled set to ItemCache

---

 rtemsspec/items.py                           | 45 +++++++++++++++--
 rtemsspec/tests/config/a.yml                 |  1 +
 rtemsspec/tests/spec-glossary/g.yml          |  1 +
 rtemsspec/tests/spec-glossary/glossary/t.yml |  1 +
 rtemsspec/tests/spec-glossary/glossary/u.yml |  1 +
 rtemsspec/tests/spec-glossary/glossary/v.yml |  1 +
 rtemsspec/tests/spec-interface/term.yml      |  1 +
 rtemsspec/tests/spec-item-cache-2/a.yml      |  1 +
 rtemsspec/tests/spec-item-cache/d/c.yml      |  1 +
 rtemsspec/tests/spec-item-cache/p.yml        |  2 +
 rtemsspec/tests/spec-sphinx/x.yml            |  1 +
 rtemsspec/tests/spec-sphinx/y.yml            |  1 +
 rtemsspec/tests/spec-sphinx/z.yml            |  1 +
 rtemsspec/tests/test_items_itemcache.py      | 12 ++++-
 rtemsspec/tests/test_rtems.py                | 22 ++++++---
 specview.py                                  | 73 ++++++++++++++--------------
 16 files changed, 116 insertions(+), 49 deletions(-)

diff --git a/rtemsspec/items.py b/rtemsspec/items.py
index 7b23d6e5..4819aa03 100644
--- a/rtemsspec/items.py
+++ b/rtemsspec/items.py
@@ -224,7 +224,7 @@ class Item:
 
     @property
     def cache(self) -> "ItemCache":
-        """ Returns the cache of the items. """
+        """ Returns the cache of the item. """
         return self._cache
 
     @property
@@ -384,8 +384,16 @@ class Item:
         self._links_to_children.append(link)
 
     def is_enabled(self, enabled: List[str]):
-        """ Returns true if the item is enabled by the specified enables. """
-        return is_enabled(enabled, self["enabled-by"])
+        """
+        Returns true if the item is enabled by the enabled set, otherwise
+        returns false.
+        """
+        return is_enabled(enabled, self._data["enabled-by"])
+
+    @property
+    def enabled(self) -> bool:
+        """ Returns true if the item is enabled, otherwise returns false. """
+        return self._data["_enabled"]
 
     @property
     def data(self) -> Any:
@@ -665,13 +673,18 @@ def _load_json_data(path: str, uid: str) -> Any:
     return data
 
 
+def _is_item_enabled(enabled: List[str], item: Item) -> bool:
+    return is_enabled(enabled, item["enabled-by"])
+
+
 class ItemCache:
     """ This class provides a cache of specification items. """
 
     def __init__(self,
                  config: Any,
-                 post_process_load: Optional[Callable[[ItemMap],
-                                                      None]] = None):
+                 post_process_load: Optional[Callable[[ItemMap], None]] = None,
+                 is_item_enabled: Callable[[List[str], Item],
+                                           bool] = _is_item_enabled):
         self._items: ItemMap = {}
         self._types: Set[str] = set()
         self.items_by_type: Dict[str, List[Item]] = {}
@@ -686,8 +699,11 @@ class ItemCache:
             self._root_type = _gather_spec_refinements(self[spec_root])
         else:
             self._root_type = None
+        self._enabled = config.get("enabled", [])
+        self._is_enabled = is_item_enabled
         for item in self._items.values():
             self._set_type(item)
+            item["_enabled"] = is_item_enabled(self._enabled, item)
 
     def __getitem__(self, uid: str) -> Item:
         return self._items[uid]
@@ -710,6 +726,24 @@ class ItemCache:
         """ Returns the types of the items. """
         return self._types
 
+    @property
+    def enabled(self) -> List[str]:
+        """ Returns the enabled set. """
+        return self._enabled
+
+    def set_enabled(self,
+                    enabled: List[str],
+                    is_item_enabled: Callable[[List[str], Item],
+                                              bool] = _is_item_enabled):
+        """
+        Sets the enabled status of all items according to the enabled set using
+        the is item enabled function.
+        """
+        self._enabled = enabled
+        self._is_enabled = is_item_enabled
+        for item in self._items.values():
+            item["_enabled"] = is_item_enabled(enabled, item)
+
     def add_volatile_item(self, uid: str, data: Any) -> Item:
         """
         Adds an item with the specified data to the cache and returns it.
@@ -720,6 +754,7 @@ class ItemCache:
         item.init_parents(self)
         item.init_children()
         self._set_type(item)
+        item["_enabled"] = self._is_enabled(self._enabled, item)
         return item
 
     def add_volatile_item_from_file(self, uid: str, path: str) -> Item:
diff --git a/rtemsspec/tests/config/a.yml b/rtemsspec/tests/config/a.yml
index 162db4e9..485f2f99 100644
--- a/rtemsspec/tests/config/a.yml
+++ b/rtemsspec/tests/config/a.yml
@@ -1,2 +1,3 @@
 a: b
 c: !include b.yml
+enabled-by: true
diff --git a/rtemsspec/tests/spec-glossary/g.yml b/rtemsspec/tests/spec-glossary/g.yml
index 86797bfc..d1275c12 100644
--- a/rtemsspec/tests/spec-glossary/g.yml
+++ b/rtemsspec/tests/spec-glossary/g.yml
@@ -1,6 +1,7 @@
 SPDX-License-Identifier: CC-BY-SA-4.0
 copyrights:
 - Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
 glossary-type: group
 links: []
 name: G
diff --git a/rtemsspec/tests/spec-glossary/glossary/t.yml b/rtemsspec/tests/spec-glossary/glossary/t.yml
index 0b82d582..dd1a9c13 100644
--- a/rtemsspec/tests/spec-glossary/glossary/t.yml
+++ b/rtemsspec/tests/spec-glossary/glossary/t.yml
@@ -1,6 +1,7 @@
 SPDX-License-Identifier: CC-BY-SA-4.0
 copyrights:
 - Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
 term: T
 glossary-type: term
 links:
diff --git a/rtemsspec/tests/spec-glossary/glossary/u.yml b/rtemsspec/tests/spec-glossary/glossary/u.yml
index 1ce28ff8..b1470ae8 100644
--- a/rtemsspec/tests/spec-glossary/glossary/u.yml
+++ b/rtemsspec/tests/spec-glossary/glossary/u.yml
@@ -1,6 +1,7 @@
 SPDX-License-Identifier: CC-BY-SA-4.0
 copyrights:
 - Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
 term: U
 glossary-type: term
 links:
diff --git a/rtemsspec/tests/spec-glossary/glossary/v.yml b/rtemsspec/tests/spec-glossary/glossary/v.yml
index dca475a7..ba40946f 100644
--- a/rtemsspec/tests/spec-glossary/glossary/v.yml
+++ b/rtemsspec/tests/spec-glossary/glossary/v.yml
@@ -1,6 +1,7 @@
 SPDX-License-Identifier: CC-BY-SA-4.0
 copyrights:
 - Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
 term: V
 glossary-type: term
 links:
diff --git a/rtemsspec/tests/spec-interface/term.yml b/rtemsspec/tests/spec-interface/term.yml
index 7bfa4124..dc49f215 100644
--- a/rtemsspec/tests/spec-interface/term.yml
+++ b/rtemsspec/tests/spec-interface/term.yml
@@ -1,3 +1,4 @@
+enabled-by: true
 term: x
 glossary-type: term
 links: []
diff --git a/rtemsspec/tests/spec-item-cache-2/a.yml b/rtemsspec/tests/spec-item-cache-2/a.yml
index d5b8c7db..d85102fe 100644
--- a/rtemsspec/tests/spec-item-cache-2/a.yml
+++ b/rtemsspec/tests/spec-item-cache-2/a.yml
@@ -1,2 +1,3 @@
+enabled-by: true
 links:
 - uid: nix
diff --git a/rtemsspec/tests/spec-item-cache/d/c.yml b/rtemsspec/tests/spec-item-cache/d/c.yml
index 51667d09..b31a8978 100644
--- a/rtemsspec/tests/spec-item-cache/d/c.yml
+++ b/rtemsspec/tests/spec-item-cache/d/c.yml
@@ -8,6 +8,7 @@ a:
     - 4
     - 5
 dict: {}
+enabled-by: true
 links:
 - role: null
   uid: ../p
diff --git a/rtemsspec/tests/spec-item-cache/p.yml b/rtemsspec/tests/spec-item-cache/p.yml
index 409b1695..d2d69d33 100644
--- a/rtemsspec/tests/spec-item-cache/p.yml
+++ b/rtemsspec/tests/spec-item-cache/p.yml
@@ -1,3 +1,5 @@
+enabled-by:
+  not: foobar
 links: []
 v: p
 x:
diff --git a/rtemsspec/tests/spec-sphinx/x.yml b/rtemsspec/tests/spec-sphinx/x.yml
index 1dd0b7c2..b18854f6 100644
--- a/rtemsspec/tests/spec-sphinx/x.yml
+++ b/rtemsspec/tests/spec-sphinx/x.yml
@@ -1,3 +1,4 @@
+enabled-by: true
 term: y
 glossary-type: term
 links: []
diff --git a/rtemsspec/tests/spec-sphinx/y.yml b/rtemsspec/tests/spec-sphinx/y.yml
index 79a22535..1cba37cd 100644
--- a/rtemsspec/tests/spec-sphinx/y.yml
+++ b/rtemsspec/tests/spec-sphinx/y.yml
@@ -1,3 +1,4 @@
+enabled-by: true
 name: foobar
 links: []
 type: other
diff --git a/rtemsspec/tests/spec-sphinx/z.yml b/rtemsspec/tests/spec-sphinx/z.yml
index d8fcbe80..be90f10c 100644
--- a/rtemsspec/tests/spec-sphinx/z.yml
+++ b/rtemsspec/tests/spec-sphinx/z.yml
@@ -1,3 +1,4 @@
+enabled-by: true
 term: z
 glossary-type: term
 links: []
diff --git a/rtemsspec/tests/test_items_itemcache.py b/rtemsspec/tests/test_items_itemcache.py
index 1b8e8f14..07cec0bf 100644
--- a/rtemsspec/tests/test_items_itemcache.py
+++ b/rtemsspec/tests/test_items_itemcache.py
@@ -38,6 +38,7 @@ def test_config_error():
 
 def test_load(tmpdir):
     config = create_item_cache_config_and_copy_spec(tmpdir, "spec-item-cache")
+    config["enabled"] = ["foobar"]
     item_count = 0
 
     def post_process_load(items):
@@ -45,6 +46,7 @@ def test_load(tmpdir):
         item_count = len(items)
 
     item_cache = ItemCache(config, post_process_load)
+    assert item_cache.enabled == ["foobar"]
     assert len(item_cache.types) == 1
     assert list(item_cache.types)[0] == ""
     assert item_count == len(item_cache.all)
@@ -56,6 +58,8 @@ def test_load(tmpdir):
     assert item_cache["/d/c"]["v"] == "c"
     assert item_cache["/p"]["v"] == "p"
     p = item_cache["/p"]
+    assert not p.enabled
+    assert p.is_enabled(["blub"])
     assert p["v"] == "p"
     assert p.map("/p") == p
     assert p.map("p") == p
@@ -63,11 +67,17 @@ def test_load(tmpdir):
     assert len(a) == 2
     assert a["/p"]["v"] == "p"
     assert a["/d/c"]["v"] == "c"
+    item_cache.set_enabled([])
+    assert p.enabled
     item_cache_2 = ItemCache(config)
     assert not item_cache_2.updates
     assert item_cache_2["/d/c"]["v"] == "c"
     with open(os.path.join(tmpdir, "spec", "d", "c.yml"), "w+") as out:
-        out.write("links:\n- role: null\n  uid: ../p\nv: x\n")
+        out.write("""enabled-by: true
+links:
+- role: null
+  uid: ../p
+v: x""")
     item_cache_3 = ItemCache(config)
     assert item_cache_3.updates
     assert item_cache_3["/d/c"]["v"] == "x"
diff --git a/rtemsspec/tests/test_rtems.py b/rtemsspec/tests/test_rtems.py
index b727b098..f13e63ba 100644
--- a/rtemsspec/tests/test_rtems.py
+++ b/rtemsspec/tests/test_rtems.py
@@ -33,22 +33,32 @@ from rtemsspec.rtems import augment_with_test_links, is_pre_qualified
 def test_is_pre_qualified():
     item_cache = EmptyItemCache()
     uid = "/constraint/constant-not-pre-qualified"
-    constraint = item_cache.add_volatile_item(uid, {"links": []})
+    constraint = item_cache.add_volatile_item(uid, {
+        "enabled-by": True,
+        "links": []
+    })
     assert is_pre_qualified(constraint)
     item = item_cache.add_volatile_item(
-        "/i", {"links": [{
-            "role": "constraint",
-            "uid": uid
-        }]})
+        "/i", {
+            "enabled-by": True,
+            "links": [{
+                "role": "constraint",
+                "uid": uid
+            }]
+        })
     assert not is_pre_qualified(item)
 
 
 def test_augment_with_test_links():
     item_cache = EmptyItemCache()
-    item = item_cache.add_volatile_item("/i", {"links": []})
+    item = item_cache.add_volatile_item("/i", {
+        "enabled-by": True,
+        "links": []
+    })
     link = {"role": "validation", "uid": "/i"}
     test_case = item_cache.add_volatile_item(
         "/t", {
+            "enabled-by": True,
             "links": [],
             "test-actions": [{
                 "checks": [{
diff --git a/specview.py b/specview.py
index 4c02b500..3f820e2d 100755
--- a/specview.py
+++ b/specview.py
@@ -139,20 +139,20 @@ def _view_interface_placment(item: Item, level: int,
             _view_interface_placment(link.item, level + 1, validated_filter)
 
 
-def _view(item: Item, level: int, role: Optional[str], validated_filter: str,
-          enabled: List[str]) -> None:
-    if not item.is_enabled(enabled):
+def _view(item: Item, level: int, role: Optional[str],
+          validated_filter: str) -> None:
+    if not item.enabled:
         return
     if not _visit_item(item, level, role, validated_filter):
         return
     for child in item.children("validation"):
-        if child.is_enabled(enabled):
+        if child.enabled:
             _visit_item(child, level + 1, "validation", validated_filter)
     _view_interface_placment(item, level + 1, validated_filter)
     for link in item.links_to_children(_CHILD_ROLES):
-        _view(link.item, level + 1, link.role, validated_filter, enabled)
+        _view(link.item, level + 1, link.role, validated_filter)
     for link in item.links_to_parents(_PARENT_ROLES):
-        _view(link.item, level + 1, link.role, validated_filter, enabled)
+        _view(link.item, level + 1, link.role, validated_filter)
 
 
 _VALIDATION_LEAF = [
@@ -195,13 +195,13 @@ _VALIDATION_LEAF = [
 _VALIDATION_ROLES = _CHILD_ROLES + ["validation"]
 
 
-def _validate(item: Item, enabled: List[str]) -> bool:
+def _validate(item: Item) -> bool:
     validated = True
     count = 0
     for link in itertools.chain(item.links_to_children(_VALIDATION_ROLES),
                                 item.links_to_parents(_PARENT_ROLES)):
-        if link.item.is_enabled(enabled):
-            validated = _validate(link.item, enabled) and validated
+        if link.item.enabled:
+            validated = _validate(link.item) and validated
             count += 1
     pre_qualified = is_pre_qualified(item)
     item["_pre_qualified"] = pre_qualified
@@ -211,23 +211,21 @@ def _validate(item: Item, enabled: List[str]) -> bool:
     return validated
 
 
-def _validation_count(item: Item, enabled: List[str]) -> int:
+def _validation_count(item: Item) -> int:
     return len(
-        list(child for child in item.children("validation")
-             if child.is_enabled(enabled)))
+        list(child for child in item.children("validation") if child.enabled))
 
 
-def _no_validation(item: Item, path: List[str],
-                   enabled: List[str]) -> List[str]:
+def _no_validation(item: Item, path: List[str]) -> List[str]:
     path_2 = path + [item.uid]
-    if not item.is_enabled(enabled):
+    if not item.enabled:
         return path_2[:-1]
-    leaf = _validation_count(item, enabled) == 0
+    leaf = _validation_count(item) == 0
     for child in item.children(_CHILD_ROLES):
-        path_2 = _no_validation(child, path_2, enabled)
+        path_2 = _no_validation(child, path_2)
         leaf = False
     for parent in item.parents(_PARENT_ROLES):
-        path_2 = _no_validation(parent, path_2, enabled)
+        path_2 = _no_validation(parent, path_2)
         leaf = False
     if leaf and not item.get("_validated", True):
         for index, component in enumerate(path_2):
@@ -264,9 +262,9 @@ def _gather_design_components(item: Item, components: List[Item]) -> bool:
     return False
 
 
-def _design(item_cache: ItemCache, enabled: List[str]) -> None:
+def _design(item_cache: ItemCache) -> None:
     for item in item_cache.all.values():
-        if not item.is_enabled(enabled):
+        if not item.enabled:
             continue
         components: List[Item] = []
         if not _gather_design_components(item, components):
@@ -316,7 +314,7 @@ def _make_row(transition_map: TransitionMap, map_idx: int,
              for co_idx, st_idx in enumerate(variant.post_cond))))
 
 
-def _action_table(enabled: List[str], item: Item) -> None:
+def _action_table(item: Item) -> None:
     rows = [
         tuple(
             itertools.chain(["Entry", "Descriptor"],
@@ -326,7 +324,7 @@ def _action_table(enabled: List[str], item: Item) -> None:
                              for condition in item["post-conditions"])))
     ]
     transition_map = TransitionMap(item)
-    for map_idx, variant in transition_map.get_variants(enabled):
+    for map_idx, variant in transition_map.get_variants(item.cache.enabled):
         rows.append(_make_row(transition_map, map_idx, variant))
     content = SphinxContent()
     content.add_simple_table(rows)
@@ -338,9 +336,10 @@ def _to_name(transition_map, co_idx: int, st_idx: int) -> str:
             f"{transition_map.post_co_idx_st_idx_to_st_name(co_idx, st_idx)}")
 
 
-def _action_list(enabled: List[str], item: Item) -> None:
+def _action_list(item: Item) -> None:
     transition_map = TransitionMap(item)
-    for post_cond, pre_conds in transition_map.get_post_conditions(enabled):
+    for post_cond, pre_conds in transition_map.get_post_conditions(
+            item.cache.enabled):
         print("")
         if post_cond[0]:
             print(transition_map.skip_idx_to_name(post_cond[0]))
@@ -436,37 +435,37 @@ def main() -> None:
                         nargs="*",
                         help="an UID of a specification item")
     args = parser.parse_args(sys.argv[1:])
-    enabled = args.enabled.split(",") if args.enabled else []
-    config = load_config("config.yml")
-    item_cache = ItemCache(config["spec"])
+    config = load_config("config.yml")["spec"]
+    config["enabled"] = args.enabled.split(",") if args.enabled else []
+    item_cache = ItemCache(config)
     augment_with_test_links(item_cache)
     augment_with_test_case_links(item_cache)
     root = item_cache["/req/root"]
 
     if args.filter == "none":
-        _validate(root, enabled)
-        _view(root, 0, None, args.validated, enabled)
+        _validate(root)
+        _view(root, 0, None, args.validated)
     elif args.filter == "action-table":
         for uid in args.UIDs:
-            _action_table(enabled, item_cache[uid])
+            _action_table(item_cache[uid])
     elif args.filter == "action-list":
         for uid in args.UIDs:
-            _action_list(enabled, item_cache[uid])
+            _action_list(item_cache[uid])
     elif args.filter == "orphan":
-        _validate(root, enabled)
+        _validate(root)
         for item in item_cache.all.values():
             if item["type"] in ["build", "spec"]:
                 continue
-            if item.is_enabled(enabled) and "_validated" not in item:
+            if item.enabled and "_validated" not in item:
                 print(item.uid)
     elif args.filter == "no-validation":
-        _validate(root, enabled)
-        _no_validation(root, [], enabled)
+        _validate(root)
+        _no_validation(root, [])
     elif args.filter == "api":
-        _validate(root, enabled)
+        _validate(root)
         _list_api(item_cache)
     elif args.filter == "design":
-        _design(item_cache, enabled)
+        _design(item_cache)
 
 
 if __name__ == "__main__":



More information about the vc mailing list