add deep_convert_keys utility, improve type checking for get_fmt_keys

This commit is contained in:
thatmattlove 2021-09-13 02:38:36 -07:00
parent 641f1e1bdd
commit bf17ec0c95

View file

@ -6,7 +6,19 @@ import sys
import json
import string
import platform
from typing import Any, Dict, Union, Optional, Sequence, Generator
from typing import (
Any,
Dict,
List,
Type,
Tuple,
Union,
TypeVar,
Callable,
Optional,
Sequence,
Generator,
)
from asyncio import iscoroutine
from pathlib import Path
from ipaddress import IPv4Address, IPv6Address, ip_address
@ -22,6 +34,8 @@ from hyperglass.constants import DRIVER_MAP
ALL_NOS = {*DRIVER_MAP.keys(), *CLASS_MAPPER.keys()}
ALL_DRIVERS = {*DRIVER_MAP.values(), "netmiko"}
DeepConvert = TypeVar("DeepConvert", bound=Dict[str, Any])
def cpu_count(multiplier: int = 0) -> int:
"""Get server's CPU core count.
@ -325,8 +339,27 @@ def get_fmt_keys(template: str) -> Sequence[str]:
`["key", "value"]`.
"""
keys = []
for block in string.Formatter.parse("", template):
for block in (b for b in string.Formatter.parse("", template) if isinstance(template, str)):
key = block[1]
if key:
keys.append(key)
return keys
def deep_convert_keys(_dict: Type[DeepConvert], predicate: Callable[[str], str]) -> DeepConvert:
"""Convert all dictionary keys and nested dictionary keys."""
converted = {}
def get_value(value: Any):
if isinstance(value, Dict):
return {predicate(k): get_value(v) for k, v in value.items()}
elif isinstance(value, List):
return [get_value(v) for v in value]
elif isinstance(value, Tuple):
return tuple(get_value(v) for v in value)
return value
for key, value in _dict.items():
converted[predicate(key)] = get_value(value)
return converted