summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2020-12-13 17:29:48 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2020-12-13 20:31:55 +0100
commit27c788bda1624a665830d34b4cc7c9337ca1ce2b (patch)
treebfc05fd07962d3ad7dc896ec434936ad9b3cbad1
parentitems: Optional post-process load in ItemCache (diff)
downloadrtems-central-27c788bda1624a665830d34b4cc7c9337ca1ce2b.tar.bz2
items: Simplify ItemMapper
-rw-r--r--rtemsspec/items.py74
-rw-r--r--rtemsspec/tests/test_items_itemcache.py10
-rw-r--r--rtemsspec/validation.py11
3 files changed, 49 insertions, 46 deletions
diff --git a/rtemsspec/items.py b/rtemsspec/items.py
index 37966417..cc46338a 100644
--- a/rtemsspec/items.py
+++ b/rtemsspec/items.py
@@ -31,7 +31,7 @@ import pickle
import string
import stat
from typing import Any, Callable, Dict, Iterable, Iterator, List, NamedTuple, \
- Mapping, Optional, Tuple, Union
+ Optional, Tuple, Union
import yaml
@@ -393,7 +393,26 @@ class ItemTemplate(string.Template):
idpattern = "[a-zA-Z0-9._/-]+(:[][a-zA-Z0-9._/-]+)?(|[a-zA-Z0-9_]+)*"
-class ItemMapper(Mapping[str, object]):
+class _ItemMapperContext(dict):
+ """ Context to map identifiers to items and attribute values. """
+ def __init__(self, mapper: "ItemMapper", item: Optional[Item],
+ prefix: Optional[str], recursive: bool):
+ super().__init__()
+ self._mapper = mapper
+ self._item = item
+ self._prefix = prefix
+ self._recursive = recursive
+
+ def __getitem__(self, identifier):
+ item, key_path, value = self._mapper.map(identifier, self._item,
+ self._prefix)
+ if self._recursive:
+ return self._mapper.substitute(value, item,
+ os.path.dirname(key_path))
+ return value
+
+
+class ItemMapper:
""" Maps identifiers to items and attribute values. """
def __init__(self, item: Item, recursive: bool = False):
self._item = item
@@ -442,9 +461,13 @@ class ItemMapper(Mapping[str, object]):
""" Returns the get value map for the item. """
return self._get_value_map.get(item.type, {})
- def map(self, identifier: str) -> Tuple[Item, str, Any]:
+ def map(self,
+ identifier: str,
+ item: Optional[Item] = None,
+ prefix: Optional[str] = None) -> Tuple[Item, str, Any]:
"""
- Maps an identifier to the corresponding item and attribute value.
+ Maps an identifier with item and prefix to the corresponding item and
+ attribute value.
"""
uid_key_path, *pipes = identifier.split("|")
colon = uid_key_path.find(":")
@@ -453,8 +476,10 @@ class ItemMapper(Mapping[str, object]):
else:
uid, key_path = uid_key_path, "/_uid"
if uid == ".":
- item = self._item
- prefix = "/".join(self._prefix)
+ if item is None:
+ item = self._item
+ if prefix is None:
+ prefix = "/".join(self._prefix)
else:
item = self._item.map(uid)
prefix = ""
@@ -465,43 +490,24 @@ class ItemMapper(Mapping[str, object]):
value = getattr(self, func)(value)
return item, key_path, value
- @contextmanager
- def _item_and_prefix(self, item: Item, prefix: str) -> Iterator[None]:
- item_2 = self._item
- prefix_2 = self._prefix
- self._item = item
- self._prefix = [prefix]
- yield
- self._item = item_2
- self._prefix = prefix_2
-
def __getitem__(self, identifier):
item, key_path, value = self.map(identifier)
if self._recursive:
- with self._item_and_prefix(item, os.path.dirname(key_path)):
- return self.substitute(value)
+ return self.substitute(value, item, os.path.dirname(key_path))
return value
- def __iter__(self):
- raise StopIteration
-
- def __len__(self):
- raise AttributeError
-
- def substitute(self, text: Optional[str]) -> str:
- """ Performs a variable substitution using the item mapper. """
- if not text:
- return ""
- return ItemTemplate(text).substitute(self)
-
- def substitute_with_prefix(self, text: Optional[str], prefix: str) -> str:
+ def substitute(self,
+ text: Optional[str],
+ item: Optional[Item] = None,
+ prefix: Optional[str] = None) -> str:
"""
- Performs a variable substitution using the item mapper with a prefix.
+ Performs a variable substitution using the item mapper with the item
+ and prefix.
"""
if not text:
return ""
- with self.prefix(prefix):
- return ItemTemplate(text).substitute(self)
+ context = _ItemMapperContext(self, item, prefix, self._recursive)
+ return ItemTemplate(text).substitute(context)
class _SpecType(NamedTuple):
diff --git a/rtemsspec/tests/test_items_itemcache.py b/rtemsspec/tests/test_items_itemcache.py
index 93afb8bf..a45f4fc1 100644
--- a/rtemsspec/tests/test_items_itemcache.py
+++ b/rtemsspec/tests/test_items_itemcache.py
@@ -128,7 +128,7 @@ def test_item_mapper(tmpdir):
assert base_mapper["d/c:v"] == "c"
mapper = Mapper(item)
assert mapper.substitute(None) == ""
- assert mapper.substitute_with_prefix(None, "v") == ""
+ assert mapper.substitute(None, prefix="v") == ""
with mapper.prefix("v"):
assert mapper[".:."] == "p"
assert mapper[".:../x/y"] == "z"
@@ -137,7 +137,7 @@ def test_item_mapper(tmpdir):
assert key_path_2 == "/v"
assert value_2 == "p"
assert mapper.substitute("$$${.:.}") == "$p"
- assert mapper.substitute_with_prefix("$$${.:.}", "v") == "$p"
+ assert mapper.substitute("$$${.:.}", prefix="v") == "$p"
with mapper.prefix("x"):
with mapper.prefix("y"):
assert mapper[".:."] == "z"
@@ -154,13 +154,9 @@ def test_item_mapper(tmpdir):
assert item_3 == item
assert key_path_3 == "/v"
assert value_3 == "p"
- with pytest.raises(StopIteration):
- for something in mapper:
- pass
- with pytest.raises(AttributeError):
- len(mapper)
recursive_mapper = ItemMapper(item, recursive=True)
assert recursive_mapper.substitute("${.:/r1/r2/r3}") == "foobar"
+ assert recursive_mapper[".:/r1/r2/r3"] == "foobar"
def test_empty_item_mapper():
diff --git a/rtemsspec/validation.py b/rtemsspec/validation.py
index 289b6a6e..3663acba 100644
--- a/rtemsspec/validation.py
+++ b/rtemsspec/validation.py
@@ -62,7 +62,10 @@ class _Mapper(ItemMapper):
""" Resets the test step counter. """
self._step = 0
- def map(self, identifier: str) -> Tuple[Item, str, Any]:
+ def map(self,
+ identifier: str,
+ item: Optional[Item] = None,
+ prefix: Optional[str] = None) -> Tuple[Item, str, Any]:
if identifier == "step":
step = self._step
self._step = step + 1
@@ -72,7 +75,7 @@ class _Mapper(ItemMapper):
inc = int(match.group(1))
self._step += inc
return self._item, "step", f"Accounts for {inc} test plan steps"
- return super().map(identifier)
+ return super().map(identifier, item, prefix)
def _add_ingroup(content: CContent, items: List["_TestItem"]) -> None:
@@ -151,9 +154,7 @@ class _TestItem:
"""
Performs a variable substitution for text with an optional prefix.
"""
- if prefix:
- return self._mapper.substitute_with_prefix(text, prefix)
- return self._mapper.substitute(text)
+ return self._mapper.substitute(text, prefix=prefix)
def add_test_case_description(
self, content: CContent,