mirror of
ssh://git.janware.com/srv/git/janware/proj/jw-python
synced 2026-01-15 09:53:32 +01:00
stree.StringTree.find(): Add method
StringTree.find(key, val) (and Config.find(), for that matter) returns a list of paths with sections containing children matching key / val pairs. One of them can be None, which acts as a wildcard. Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
parent
a9fa274bb1
commit
b464f20e6c
2 changed files with 78 additions and 1 deletions
|
|
@ -158,3 +158,9 @@ class Config(): # export
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return self.__conf.content
|
return self.__conf.content
|
||||||
|
|
||||||
|
def find(self, key: str|None, val: str|None, match:StringTree.Match=StringTree.Match.Equal) -> list[str]:
|
||||||
|
return self.__conf.find(key, val, match=match)
|
||||||
|
|
||||||
|
#def __getattr__(self, name: str):
|
||||||
|
# return getattr(self.__conf, name)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
from collections import OrderedDict
|
|
||||||
from typing import Any, List, Optional, Union
|
from typing import Any, List, Optional, Union
|
||||||
|
|
||||||
|
import re, fnmatch
|
||||||
|
from collections import OrderedDict
|
||||||
|
from enum import Enum, auto
|
||||||
|
|
||||||
from jwutils.log import *
|
from jwutils.log import *
|
||||||
|
|
||||||
def quote(s):
|
def quote(s):
|
||||||
|
|
@ -227,3 +231,70 @@ class StringTree: # export
|
||||||
slog(prio, ",------------" + msg + "----------- >", caller=caller)
|
slog(prio, ",------------" + msg + "----------- >", caller=caller)
|
||||||
self.__dump(prio, indent=0, caller=caller)
|
self.__dump(prio, indent=0, caller=caller)
|
||||||
slog(prio, "`------------" + msg + "----------- <", caller=caller)
|
slog(prio, "`------------" + msg + "----------- <", caller=caller)
|
||||||
|
|
||||||
|
class Match(Enum):
|
||||||
|
Equal = auto()
|
||||||
|
RegExArg = auto()
|
||||||
|
RegExConf = auto()
|
||||||
|
GlobArg = auto()
|
||||||
|
GlobConf = auto()
|
||||||
|
|
||||||
|
def __find(self, key: str|None, val: str|None, match: Match, depth_first: bool):
|
||||||
|
|
||||||
|
def __children():
|
||||||
|
for name, child in self.children.items():
|
||||||
|
ret.extend(child.__find(key, val, match, depth_first))
|
||||||
|
|
||||||
|
def __self():
|
||||||
|
_val = self.value()
|
||||||
|
_content = self.content
|
||||||
|
try:
|
||||||
|
if (
|
||||||
|
(key == _content and matcher(val, _val))
|
||||||
|
or (key is None and matcher(val, _val))
|
||||||
|
or (key == _content and val is None)
|
||||||
|
):
|
||||||
|
ret.append(self)
|
||||||
|
except Exception as e:
|
||||||
|
if isinstance(e, re.PatternError):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
def __debug_matcher(matcher, log_level=DEBUG):
|
||||||
|
def __matcher(x, y):
|
||||||
|
slog(log_level, f'Comparing "{x}" ~ "{y}"')
|
||||||
|
return matcher(x, y)
|
||||||
|
return __matcher
|
||||||
|
|
||||||
|
if not self.children:
|
||||||
|
return []
|
||||||
|
|
||||||
|
matcher = lambda x, y: x == y
|
||||||
|
match match:
|
||||||
|
case self.Match.Equal:
|
||||||
|
pass
|
||||||
|
case self.Match.RegExArg:
|
||||||
|
matcher = lambda x, y: re.search(x, y) is not None
|
||||||
|
case self.Match.RegExConf:
|
||||||
|
matcher = lambda x, y: re.search(y, x) is not None
|
||||||
|
case self.Match.GlobArg:
|
||||||
|
matcher = lambda x, y: fnmatch.fnmatch(y, x)
|
||||||
|
case self.Match.GlobConf:
|
||||||
|
matcher = lambda x, y: fnmatch.fnmatch(x, y)
|
||||||
|
case _:
|
||||||
|
raise NotImplementedError(f'Matcher {match} is not yet implemented')
|
||||||
|
|
||||||
|
ret = []
|
||||||
|
|
||||||
|
if depth_first:
|
||||||
|
__children()
|
||||||
|
__self()
|
||||||
|
else:
|
||||||
|
__self()
|
||||||
|
__children()
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def find(self, key: str|None=None, val: str|None=None, match: Match=Match.Equal, depth_first: bool=False):
|
||||||
|
return [ node.parent.path for node in self.__find(key, val, match=match, depth_first=depth_first)]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue