Newer
Older
# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

Lluis Gifre Renom
committed
from typing import Any, List, Optional, Union
from apscheduler.job import Job
class TreeNode(anytree.node.Node):
def __init__(self, name, parent=None, children=None, **kwargs) -> None:
super().__init__(name, parent=parent, children=children, **kwargs)
self.value : Optional[Any] = None
def get_full_path(self):
return self.separator.join([''] + [str(node.name) for node in self.path])
class RawStyle(anytree.render.AbstractStyle):
def __init__(self):
"""
Raw style.
>>> from anytree import Node, RenderTree
>>> root = Node("root")
>>> s0 = Node("sub0", parent=root)
>>> s0b = Node("sub0B", parent=s0)
>>> s0a = Node("sub0A", parent=s0)
>>> s1 = Node("sub1", parent=root)
>>> print(RenderTree(root, style=RawStyle()))
Node('/root')
Node('/root/sub0')
Node('/root/sub0/sub0B')
Node('/root/sub0/sub0A')
Node('/root/sub1')
"""

Lluis Gifre Renom
committed
super(RawStyle, self).__init__('', '', '')

Lluis Gifre Renom
committed
def get_subnode(
resolver : anytree.Resolver, root : TreeNode, key_or_path : Union[str, List[str]], default : Optional[Any] = None):
if isinstance(key_or_path, str): key_or_path = key_or_path.split('/')

Lluis Gifre Renom
committed
for path_item in key_or_path:
try:
node = resolver.get(node, path_item)
except anytree.ChildResolverError:
return default
return node

Lluis Gifre Renom
committed
def set_subnode_value(resolver : anytree.Resolver, root : TreeNode, key_or_path : Union[str, List[str]], value : Any):
if isinstance(key_or_path, str): key_or_path = key_or_path.split('/')

Lluis Gifre Renom
committed
for path_item in key_or_path:
try:
node = resolver.get(node, path_item)
except anytree.ChildResolverError:
node = TreeNode(path_item, parent=node)
if isinstance(node.value, dict) and isinstance(value, dict):
node.value.update(value)
else:
node.value = value
def dump_subtree(root : TreeNode):
if not isinstance(root, TreeNode): raise Exception('root must be a TreeNode')
results = []
for row in anytree.RenderTree(root, style=RawStyle()):
node : TreeNode = row.node
path = node.get_full_path()[2:] # get full path except the heading root placeholder "/."
if len(path) == 0: continue
value = node.value
if value is None: continue
if isinstance(value, Job): value = str(value)
results.append((path, value))
return results