moto/moto/utilities/utils.py
2023-02-01 16:30:58 -01:00

103 lines
2.7 KiB
Python

import json
import hashlib
import pkgutil
from collections.abc import MutableMapping
from typing import Any, Dict, List, TypeVar, Tuple
def str2bool(v):
if v in ("yes", True, "true", "True", "TRUE", "t", "1"):
return True
elif v in ("no", False, "false", "False", "FALSE", "f", "0"):
return False
def load_resource(package: str, resource: str) -> Dict[str, Any]:
"""
Open a file, and return the contents as JSON.
Usage:
load_resource(__name__, "resources/file.json")
"""
resource = pkgutil.get_data(package, resource)
return json.loads(resource)
def load_resource_as_str(package: str, resource: str) -> str:
resource = pkgutil.get_data(package, resource)
return resource.decode("utf-8")
def merge_multiple_dicts(*args: Any) -> Dict[str, any]:
result = {}
for d in args:
result.update(d)
return result
RESOURCE_TYPE = TypeVar("RESOURCE_TYPE")
def filter_resources(
resources: List[RESOURCE_TYPE],
filters: Any,
attr_pairs: Tuple[Tuple[str, str], ...],
) -> List[RESOURCE_TYPE]:
"""
Used to filter resources. Usually in get and describe apis.
"""
result = resources.copy()
for resource in resources:
for attrs in attr_pairs:
values = filters.get(attrs[0]) or None
if values:
instance = getattr(resource, attrs[1])
if (len(attrs) <= 2 and instance not in values) or (
len(attrs) == 3 and instance.get(attrs[2]) not in values
):
result.remove(resource)
break
return result
def md5_hash(data: Any = None) -> Any:
"""
MD5-hashing for non-security usecases.
Required for Moto to work in FIPS-enabled systems
"""
args = (data,) if data else ()
try:
return hashlib.md5(*args, usedforsecurity=False)
except TypeError:
# The usedforsecurity-parameter is only available as of Python 3.9
return hashlib.md5(*args)
class LowercaseDict(MutableMapping):
"""A dictionary that lowercases all keys"""
def __init__(self, *args, **kwargs):
self.store = dict()
self.update(dict(*args, **kwargs)) # use the free update to set keys
def __getitem__(self, key):
return self.store[self._keytransform(key)]
def __setitem__(self, key, value):
self.store[self._keytransform(key)] = value
def __delitem__(self, key):
del self.store[self._keytransform(key)]
def __iter__(self):
return iter(self.store)
def __len__(self):
return len(self.store)
def __repr__(self):
return str(self.store)
def _keytransform(self, key):
return key.lower()