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
|
|
@ -1,7 +1,11 @@
|
|||
from __future__ import annotations
|
||||
from collections import OrderedDict
|
||||
|
||||
from typing import Any, List, Optional, Union
|
||||
|
||||
import re, fnmatch
|
||||
from collections import OrderedDict
|
||||
from enum import Enum, auto
|
||||
|
||||
from jwutils.log import *
|
||||
|
||||
def quote(s):
|
||||
|
|
@ -227,3 +231,70 @@ class StringTree: # export
|
|||
slog(prio, ",------------" + msg + "----------- >", caller=caller)
|
||||
self.__dump(prio, indent=0, 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