summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2020-10-23 10:41:16 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2020-10-23 10:41:16 +0200
commit7a76faee8ce2a5a4ab34b9213201fc8f51746704 (patch)
tree3b0ab555838911bdf15c1d6b0e077f73cc7b4ed1
parentitems: Add Item parent() and child() methods (diff)
downloadrtems-central-7a76faee8ce2a5a4ab34b9213201fc8f51746704.tar.bz2
items: Add ItemCache.add_volatile_item()
-rw-r--r--rtemsspec/items.py82
-rw-r--r--rtemsspec/tests/test_items_itemcache.py5
2 files changed, 58 insertions, 29 deletions
diff --git a/rtemsspec/items.py b/rtemsspec/items.py
index 9dd741fd..fdd37eb4 100644
--- a/rtemsspec/items.py
+++ b/rtemsspec/items.py
@@ -297,7 +297,7 @@ class Item:
return item
raise IndexError
- def init_parents(self, item_cache: "ItemCache"):
+ def init_parents(self, item_cache: "ItemCache") -> None:
""" Initializes the list of links to parents of this items. """
for data in self._data["links"]:
try:
@@ -308,6 +308,11 @@ class Item:
f"to non-existing item '{data['uid']}'")
raise KeyError(msg) from err
+ def init_children(self) -> None:
+ """ Initializes the list of links to children of this items. """
+ for link in self.links_to_parents():
+ link.item.add_link_to_child(Link.create(link, self))
+
def add_link_to_child(self, link: Link):
""" Adds a link to a child item of this items. """
self._links_to_children.append(link)
@@ -482,13 +487,27 @@ def _gather_spec_refinements(item: Item) -> Optional[_SpecType]:
return new_type
+def _load_item(path: str, uid: str) -> Any:
+ with open(path, "r") as src:
+ data = yaml.safe_load(src.read())
+ data["_file"] = os.path.abspath(path)
+ data["_uid"] = uid
+ return data
+
+
class ItemCache:
""" This class provides a cache of specification items. """
def __init__(self, config: Any):
self._items = {} # type: ItemMap
self._top_level = {} # type: ItemMap
self._load_items(config)
- self._set_types(config)
+ spec_root = config["spec-type-root-uid"]
+ if spec_root:
+ self._root_type = _gather_spec_refinements(self[spec_root])
+ else:
+ self._root_type = None
+ for item in self._items.values():
+ self._set_type(item)
def __getitem__(self, uid: str) -> Item:
return self._items[uid]
@@ -503,6 +522,26 @@ class ItemCache:
""" Returns the map of top-level specification items. """
return self._top_level
+ def add_volatile_item(self, path: str, uid: str) -> Item:
+ """
+ Adds an item stored in the specified file to the cache and returns it.
+
+ The item is not added to the persistent cache storage.
+ """
+ data = _load_item(path, uid)
+ item = self._add_item(uid, data)
+ item.init_parents(self)
+ item.init_children()
+ self._set_type(item)
+ return item
+
+ def _add_item(self, uid: str, data: Any) -> Item:
+ item = Item(self, uid, data)
+ self._items[uid] = item
+ if not item["links"]:
+ self._top_level[uid] = item
+ return item
+
def _load_items_in_dir(self, base: str, path: str, cache_file: str,
update_cache: bool) -> None:
data_by_uid = {} # type: Dict[str, Any]
@@ -512,11 +551,7 @@ class ItemCache:
if name.endswith(".yml") and not name.startswith("."):
uid = "/" + os.path.relpath(path2, base).replace(
".yml", "")
- with open(path2, "r") as yaml_src:
- data = yaml.safe_load(yaml_src.read())
- data["_file"] = os.path.abspath(path2)
- data["_uid"] = uid
- data_by_uid[uid] = data
+ data_by_uid[uid] = _load_item(path2, uid)
os.makedirs(os.path.dirname(cache_file), exist_ok=True)
with open(cache_file, "wb") as out:
pickle.dump(data_by_uid, out)
@@ -524,10 +559,7 @@ class ItemCache:
with open(cache_file, "rb") as pickle_src:
data_by_uid = pickle.load(pickle_src)
for uid, data in iter(data_by_uid.items()):
- item = Item(self, uid, data)
- self._items[uid] = item
- if not item["links"]:
- self._top_level[uid] = item
+ self._add_item(uid, data)
def _load_items_recursive(self, base: str, path: str,
cache_dir: str) -> None:
@@ -554,9 +586,7 @@ class ItemCache:
def _init_children(self) -> None:
for uid in sorted(self._items):
- item = self._items[uid]
- for link in item.links_to_parents():
- link.item.add_link_to_child(Link.create(link, item))
+ self._items[uid].init_children()
def _load_items(self, config: Any) -> None:
cache_dir = os.path.abspath(config["cache-directory"])
@@ -565,21 +595,15 @@ class ItemCache:
self._init_parents()
self._init_children()
- def _set_types(self, config: Any) -> None:
- spec_root = config["spec-type-root-uid"]
- if spec_root:
- root_type = _gather_spec_refinements(self[spec_root])
- else:
- root_type = None
- for item in self._items.values():
- spec_type = root_type
- value = item.data
- path = [] # type: List[str]
- while spec_type is not None:
- type_name = value[spec_type.key]
- path.append(type_name)
- spec_type = spec_type.refinements[type_name]
- item["_type"] = "/".join(path)
+ def _set_type(self, item: Item) -> None:
+ spec_type = self._root_type
+ value = item.data
+ path = [] # type: List[str]
+ while spec_type is not None:
+ type_name = value[spec_type.key]
+ path.append(type_name)
+ spec_type = spec_type.refinements[type_name]
+ item["_type"] = "/".join(path)
class EmptyItemCache(ItemCache):
diff --git a/rtemsspec/tests/test_items_itemcache.py b/rtemsspec/tests/test_items_itemcache.py
index b8507fc4..b2205864 100644
--- a/rtemsspec/tests/test_items_itemcache.py
+++ b/rtemsspec/tests/test_items_itemcache.py
@@ -60,6 +60,11 @@ def test_load(tmpdir):
out.write("links:\n- role: null\n uid: ../p\nv: x\n")
item_cache_3 = ItemCache(config)
assert item_cache_3["/d/c"]["v"] == "x"
+ item = item_cache_3.add_volatile_item(
+ os.path.join(os.path.dirname(__file__), "spec/root.yml"), "/foo/bar")
+ assert item.uid == "/foo/bar"
+ assert item.type == ""
+ assert item["type"] == "spec"
def test_load_link_error(tmpdir):