summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2020-12-01 12:07:29 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2020-12-01 14:08:48 +0100
commite165b7d684ec73f1010be3c53d73dbf990f9ac4e (patch)
treebd469b4653decbd8c7964adacf0686ff69e72d8f
parentglossary: Use ItemMapper.add_get_value() (diff)
downloadrtems-central-e165b7d684ec73f1010be3c53d73dbf990f9ac4e.tar.bz2
items: Enable custom get value for lists
-rw-r--r--rtemsspec/applconfig.py34
-rw-r--r--rtemsspec/interface.py41
-rw-r--r--rtemsspec/items.py46
-rw-r--r--rtemsspec/tests/test_items_itemcache.py11
4 files changed, 59 insertions, 73 deletions
diff --git a/rtemsspec/applconfig.py b/rtemsspec/applconfig.py
index 51f5736e..6e3691ce 100644
--- a/rtemsspec/applconfig.py
+++ b/rtemsspec/applconfig.py
@@ -321,10 +321,6 @@ def _generate(group: Item, options: ItemMap, content: _ContentAdaptor) -> None:
content.add_licence_and_copyrights()
-def _get_value_none(_ctx: ItemGetValueContext) -> Any:
- return None
-
-
def _sphinx_ref(ref: str) -> str:
return f":ref:`{ref}`"
@@ -354,17 +350,14 @@ _SPHINX_DOC_REFS = {
}
-def _get_value_sphinx_reference(ctx: ItemGetValueContext) -> Any:
- return _SPHINX_DOC_REFS[ctx.key]
+def _get_value_sphinx_reference(_ctx: ItemGetValueContext) -> Any:
+ return _SPHINX_DOC_REFS
def _add_sphinx_get_values(mapper: ItemMapper) -> None:
- for key in _SPHINX_DOC_REFS:
- for opt in ["feature-enable", "feature", "initializer", "integer"]:
- doc_ref = f"interface/appl-config-option/{opt}:/document-reference"
- mapper.add_get_value(doc_ref, _get_value_none)
- mapper.add_get_value(f"{doc_ref}/{key}",
- _get_value_sphinx_reference)
+ for opt in ["feature-enable", "feature", "initializer", "integer"]:
+ doc_ref = f"interface/appl-config-option/{opt}:/document-reference"
+ mapper.add_get_value(doc_ref, _get_value_sphinx_reference)
def _c_user_ref(ref: str, name: str) -> str:
@@ -427,8 +420,8 @@ _DOXYGEN_DOC_REFS = {
}
-def _get_value_doxygen_reference(ctx: ItemGetValueContext) -> Any:
- return _DOXYGEN_DOC_REFS[ctx.key]
+def _get_value_doxygen_reference(_ctx: ItemGetValueContext) -> Any:
+ return _DOXYGEN_DOC_REFS
def _get_value_doxygen_url(ctx: ItemGetValueContext) -> Any:
@@ -448,14 +441,11 @@ def _get_value_doxygen_unspecfied_type(ctx: ItemGetValueContext) -> Any:
def _add_doxygen_get_values(mapper: ItemMapper) -> None:
- for key in _DOXYGEN_DOC_REFS:
- for opt in ["feature-enable", "feature", "initializer", "integer"]:
- doc_ref = f"interface/appl-config-option/{opt}:/document-reference"
- mapper.add_get_value(doc_ref, _get_value_none)
- mapper.add_get_value(f"{doc_ref}/{key}",
- _get_value_doxygen_reference)
- name = f"interface/appl-config-option/{opt}:/name"
- mapper.add_get_value(name, get_value_hash)
+ for opt in ["feature-enable", "feature", "initializer", "integer"]:
+ doc_ref = f"interface/appl-config-option/{opt}:/document-reference"
+ mapper.add_get_value(doc_ref, _get_value_doxygen_reference)
+ name = f"interface/appl-config-option/{opt}:/name"
+ mapper.add_get_value(name, get_value_hash)
mapper.add_get_value("interface/define:/name", get_value_hash)
mapper.add_get_value("interface/function:/name",
get_value_doxygen_function)
diff --git a/rtemsspec/interface.py b/rtemsspec/interface.py
index 87e6f8b9..04536232 100644
--- a/rtemsspec/interface.py
+++ b/rtemsspec/interface.py
@@ -31,7 +31,8 @@ from typing import Any, Callable, Dict, Iterator, List, Union, Set
from rtemsspec.content import CContent, CInclude, enabled_by_to_exp, \
ExpressionMapper, get_value_double_colon, get_value_doxygen_function, \
get_value_hash
-from rtemsspec.items import Item, ItemCache, ItemGetValueContext, ItemMapper
+from rtemsspec.items import Item, ItemCache, ItemGetValueContext, \
+ ItemGetValueMap, ItemMapper
ItemMap = Dict[str, Item]
Lines = Union[str, List[str]]
@@ -63,25 +64,25 @@ class _InterfaceMapper(ItemMapper):
super().__init__(node.item)
self._node = node
self._code_or_doc = "doc"
- self.add_get_value("interface/forward-declaration:code:/name",
+ self.add_get_value("interface/forward-declaration/code:/name",
_get_value_forward_declaration)
- self.add_get_value("interface/forward-declaration:doc:/name",
+ self.add_get_value("interface/forward-declaration/doc:/name",
_get_value_forward_declaration)
- self.add_get_value("interface/function:doc:/name",
+ self.add_get_value("interface/function/doc:/name",
get_value_doxygen_function)
- self.add_get_value("interface/enumerator:doc:/name",
+ self.add_get_value("interface/enumerator/doc:/name",
get_value_double_colon)
- self.add_get_value("interface/typedef:doc:/name",
+ self.add_get_value("interface/typedef/doc:/name",
get_value_double_colon)
- self.add_get_value("interface/define:doc:/name", get_value_hash)
- self.add_get_value("interface/enum:doc:/name", get_value_hash)
- self.add_get_value("interface/macro:doc:/name",
+ self.add_get_value("interface/define/doc:/name", get_value_hash)
+ self.add_get_value("interface/enum/doc:/name", get_value_hash)
+ self.add_get_value("interface/macro/doc:/name",
get_value_doxygen_function)
- self.add_get_value("interface/variable:doc:/name", get_value_hash)
+ self.add_get_value("interface/variable/doc:/name", get_value_hash)
for opt in ["feature-enable", "feature", "initializer", "integer"]:
- name = f"interface/appl-config-option/{opt}:doc:/name"
+ name = f"interface/appl-config-option/{opt}/doc:/name"
self.add_get_value(name, get_value_hash)
- self.add_get_value("interface/unspecified-function:doc:/name",
+ self.add_get_value("interface/unspecified-function/doc:/name",
get_value_doxygen_function)
@contextmanager
@@ -92,19 +93,17 @@ class _InterfaceMapper(ItemMapper):
yield
self._code_or_doc = code_or_doc
- def get_value(self, ctx: ItemGetValueContext) -> Any:
- if self._code_or_doc == "code" and ctx.item["type"] == "interface":
+ def get_value_map(self, item: Item) -> ItemGetValueMap:
+ if self._code_or_doc == "code" and item["type"] == "interface":
node = self._node
header_file = node.header_file
- if ctx.item["interface-type"] == "enumerator":
- for child in ctx.item.children("interface-enumerator"):
+ if item["interface-type"] == "enumerator":
+ for child in item.children("interface-enumerator"):
header_file.add_includes(child)
else:
- header_file.add_includes(ctx.item)
- header_file.add_dependency(node, ctx.item)
- return super().get_value(
- ItemGetValueContext(ctx.item, f"{self._code_or_doc}:{ctx.path}",
- ctx.value, ctx.key, ctx.index))
+ header_file.add_includes(item)
+ header_file.add_dependency(node, item)
+ return self._get_value_map.get(f"{item.type}/{self._code_or_doc}", {})
def enabled_by_to_defined(self, enabled_by: str) -> str:
"""
diff --git a/rtemsspec/items.py b/rtemsspec/items.py
index 5b7a95af..12ecfb42 100644
--- a/rtemsspec/items.py
+++ b/rtemsspec/items.py
@@ -42,14 +42,10 @@ class ItemGetValueContext(NamedTuple):
key: str
index: Any # should be int, but this triggers a mypy error
- @property
- def type_path_key(self) -> str:
- """ Returns the item type followed the path to the key. """
- return f"{self.item.type}:{os.path.join(self.path, self.key)}"
-
ItemMap = Dict[str, "Item"]
ItemGetValue = Callable[[ItemGetValueContext], Any]
+ItemGetValueMap = Dict[str, Tuple[ItemGetValue, Any]]
def _is_enabled_op_and(enabled: List[str], enabled_by: Any) -> bool:
@@ -185,10 +181,8 @@ class Item:
"""
return self._data.get(key, default)
- def get_by_normalized_key_path(
- self,
- normalized_key_path: str,
- get_value: ItemGetValue = _get_value) -> Any:
+ def get_by_normalized_key_path(self, normalized_key_path: str,
+ get_value_map: ItemGetValueMap) -> Any:
"""
Gets the attribute value corresponding to the normalized key path.
"""
@@ -201,20 +195,16 @@ class Item:
except IndexError:
index = -1
ctx = ItemGetValueContext(self, path, value, parts[0], index)
- try:
- value = get_value(ctx)
- except KeyError:
- value = _get_value(ctx)
+ get_value, get_value_map = get_value_map.get(
+ parts[0], (_get_value, {}))
+ value = get_value(ctx)
path = os.path.join(path, key)
return value
- def get_by_key_path(self,
- key_path: str,
- prefix: str = "",
- get_value: ItemGetValue = _get_value) -> Any:
+ def get_by_key_path(self, key_path: str, prefix: str = "") -> Any:
""" Gets the attribute value corresponding to the key path. """
return self.get_by_normalized_key_path(
- normalize_key_path(key_path, prefix), get_value)
+ normalize_key_path(key_path, prefix), {})
@property
def uid(self) -> str:
@@ -378,7 +368,7 @@ class ItemMapper(Mapping[str, object]):
self._item = item
self._recursive = recursive
self._prefix = [""]
- self._get_value = {} # type: Dict[str, ItemGetValue]
+ self._get_value_map = {} # type: Dict[str, ItemGetValueMap]
@property
def item(self) -> Item:
@@ -395,7 +385,12 @@ class ItemMapper(Mapping[str, object]):
"""
Adds a get value for the specified type and key path.
"""
- self._get_value[type_path_key] = get_value
+ type_name, path_key = type_path_key.split(":")
+ keys = path_key.strip("/").split("/")
+ get_value_map = self._get_value_map.setdefault(type_name, {})
+ for key in keys[:-1]:
+ _, get_value_map = get_value_map.setdefault(key, (_get_value, {}))
+ get_value_map[keys[-1]] = (get_value, {})
def push_prefix(self, prefix: str) -> None:
""" Pushes a key path prefix. """
@@ -412,6 +407,10 @@ class ItemMapper(Mapping[str, object]):
yield
self.pop_prefix()
+ def get_value_map(self, item: Item) -> ItemGetValueMap:
+ """ 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]:
"""
Maps an identifier to the corresponding item and attribute value.
@@ -429,7 +428,8 @@ class ItemMapper(Mapping[str, object]):
item = self._item.map(uid)
prefix = ""
key_path = normalize_key_path(key_path, prefix)
- value = item.get_by_normalized_key_path(key_path, self.get_value)
+ value = item.get_by_normalized_key_path(key_path,
+ self.get_value_map(item))
for func in pipes:
value = getattr(self, func)(value)
return item, key_path, value
@@ -472,10 +472,6 @@ class ItemMapper(Mapping[str, object]):
with self.prefix(prefix):
return ItemTemplate(text).substitute(self)
- def get_value(self, ctx: ItemGetValueContext) -> Any:
- """ Gets a value by key and optional index. """
- return self._get_value[ctx.type_path_key](ctx)
-
class _SpecType(NamedTuple):
key: str
diff --git a/rtemsspec/tests/test_items_itemcache.py b/rtemsspec/tests/test_items_itemcache.py
index 05affc24..4331b335 100644
--- a/rtemsspec/tests/test_items_itemcache.py
+++ b/rtemsspec/tests/test_items_itemcache.py
@@ -96,6 +96,11 @@ expected <block end>, but found ':'
ItemCache(config)
+def get_x_to_b_value(ctx):
+ assert ctx.key == "x-to-b"
+ return ctx.value["b"]
+
+
class Mapper(ItemMapper):
def __init__(self, item):
super().__init__(item)
@@ -109,11 +114,6 @@ class Mapper(ItemMapper):
def dup(self, value):
return value + value
- def get_value(self, ctx):
- if ctx.key == "x-to-b":
- return ctx.value["b"]
- raise KeyError
-
def test_item_mapper(tmpdir):
config = create_item_cache_config_and_copy_spec(tmpdir, "spec-item-cache")
@@ -141,6 +141,7 @@ def test_item_mapper(tmpdir):
assert mapper["d/c:v"] == "c"
assert mapper["d/c:a/b"] == "e"
assert mapper["d/c:a/b|u"] == "ue"
+ mapper.add_get_value(":/a/x-to-b", get_x_to_b_value)
assert mapper["d/c:a/x-to-b|u|v"] == "vue"
assert mapper["d/c:a/f[1]"] == 2
assert mapper["d/c:a/../a/f[3]/g[0]|dup"] == 8