140 lines
3.9 KiB
Python
140 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from typing import Any, Self, Sequence, Optional
|
|
from re import Match as REMatch
|
|
from Utils.Check import Check
|
|
from Utils.Options import Options
|
|
from Utils.Patterns import RE
|
|
|
|
class Common:
|
|
|
|
GET_DICTIONARY_OPTIONS:Options = Options(Options.NO_OVERWRITE)
|
|
GET_VALUE_OPTIONS:Options = Options(Options.ALLOW_NULLS)
|
|
|
|
@classmethod
|
|
def get_keys(cls:type[Self], *items:Any|None) -> list[str]:
|
|
|
|
keys:list[str] = []
|
|
item:Any|None
|
|
|
|
for item in items:
|
|
if Check.is_key(item):
|
|
item in keys or keys.append(item)
|
|
elif Check.is_array(item):
|
|
|
|
key:str
|
|
|
|
for key in cls.get_keys(*item):
|
|
key in keys or keys.append(key)
|
|
|
|
return keys
|
|
|
|
@classmethod
|
|
def get_dictionaries(cls:type[Self], *items:Any|None) -> list[dict[str, Any|None]]:
|
|
|
|
dictionaries:list[dict[str, Any|None]] = []
|
|
item:Any|None
|
|
|
|
for item in items:
|
|
if Check.is_dictionary(item):
|
|
item in dictionaries or dictionaries.append(item)
|
|
elif Check.is_array(item):
|
|
|
|
dictionary:dict
|
|
|
|
for dictionary in cls.get_dictionaries(*item):
|
|
dictionary in dictionaries or dictionaries.append(dictionary)
|
|
|
|
return dictionaries
|
|
|
|
@classmethod
|
|
def get_dictionary(cls:type[Self], items:Any|None, custom_options:int = 0) -> dict[str, Any|None]:
|
|
|
|
dictionary:dict[str, Any|None] = {}
|
|
|
|
options:Options = Options(custom_options, cls.GET_DICTIONARY_OPTIONS)
|
|
|
|
if Check.is_dictionary(items):
|
|
dictionary = items
|
|
elif Check.is_array(items):
|
|
|
|
item:Any|None
|
|
|
|
for item in items:
|
|
|
|
key:str
|
|
value:Any|None
|
|
|
|
for key, value in cls.get_dictionary(item, options).items():
|
|
if options.overwrite or key not in dictionary:
|
|
dictionary[key] = value
|
|
|
|
return dictionary
|
|
|
|
@classmethod
|
|
def get_value(cls:type[Self],
|
|
keys:str|Sequence[str],
|
|
inputs:dict[str, Any|None]|Sequence[Any|None],
|
|
default:Optional[Any] = None,
|
|
custom_options:int = 0
|
|
) -> Any|None:
|
|
|
|
options:Options = Options(custom_options, cls.GET_VALUE_OPTIONS)
|
|
|
|
if len(keys := cls.get_keys(keys)):
|
|
|
|
subinputs:dict[str, Any|None]
|
|
|
|
for subinputs in cls.get_dictionaries(inputs):
|
|
|
|
key:str
|
|
|
|
for key in keys:
|
|
if key in subinputs and (
|
|
options.allow_null or
|
|
subinputs[key] is not None
|
|
):
|
|
return subinputs[key]
|
|
return default
|
|
|
|
@staticmethod
|
|
def get_array(value:Any|None) -> list[Any]:
|
|
return (
|
|
value if isinstance(value, list) else
|
|
list(value) if isinstance(value, (set, tuple)) else
|
|
[value])
|
|
|
|
@staticmethod
|
|
def get_strings(value:Any|None) -> list[str]:
|
|
|
|
strings:list[str] = []
|
|
item:Any|None
|
|
|
|
for item in Common.get_array(value):
|
|
if Check.is_string(item):
|
|
item in strings or strings.append(item)
|
|
elif Check.is_array(item):
|
|
strings.extend(Common.get_strings(item))
|
|
|
|
return strings
|
|
|
|
@classmethod
|
|
def string_variables(cls:type[Self],
|
|
string:str,
|
|
variables:dict[str, Any|None],
|
|
default:Optional[str] = None
|
|
) -> str:
|
|
|
|
variables = Common.get_dictionary(variables)
|
|
|
|
def callback(matches:REMatch) -> str:
|
|
|
|
key:str = matches.group(1)
|
|
|
|
return (
|
|
str(variables[key]) if key in variables else
|
|
default if default is not None else
|
|
matches.group(0))
|
|
|
|
return RE.STRING_VARIABLES.sub(callback, string) |