File size: 3,558 Bytes
6dd8cc1 5901c08 3776396 fd7aa63 8ae904e b6719ff fd7aa63 4c76401 118aaef 3776396 4c76401 118aaef 740f26d fd7aa63 740f26d fd7aa63 3776396 6dd8cc1 5901c08 6dd8cc1 8ae904e b6719ff 23cdef0 b6719ff 23cdef0 b6719ff |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
import json
from functools import lru_cache
from typing import Any, Dict
import pkg_resources
from .text_utils import is_made_of_sub_strings
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
def flatten_dict(
d: Dict[str, Any], parent_key: str = "", sep: str = "_"
) -> Dict[str, Any]:
items = []
for k, v in d.items():
new_key = parent_key + sep + k if parent_key else k
if isinstance(v, dict):
items.extend(flatten_dict(v, new_key, sep=sep).items())
else:
items.append((new_key, v))
return dict(items)
@lru_cache(maxsize=None)
def artifacts_json_cache(artifact_path):
return load_json(artifact_path)
def load_json(path):
with open(path) as f:
try:
return json.load(f)
except json.decoder.JSONDecodeError as e:
with open(path) as f:
file_content = "\n".join(f.readlines())
raise RuntimeError(
f"Failed to decode json file at '{path}' with file content:\n{file_content}"
) from e
def save_json(path, data):
with open(path, "w") as f:
dumped = json.dumps(data, indent=4, ensure_ascii=False)
f.write(dumped)
f.write("\n")
def is_package_installed(package_name):
"""Check if a package is installed.
Parameters:
- package_name (str): The name of the package to check.
Returns:
- bool: True if the package is installed, False otherwise.
"""
try:
pkg_resources.get_distribution(package_name)
return True
except pkg_resources.DistributionNotFound:
return False
def is_module_available(module_name):
"""Check if a module is available in the current Python environment.
Parameters:
- module_name (str): The name of the module to check.
Returns:
- bool: True if the module is available, False otherwise.
"""
try:
__import__(module_name)
return True
except ImportError:
return False
def safe_eval(expression: str, context: dict, allowed_tokens: list) -> any:
"""Evaluates a given expression in a restricted environment, allowing only specified tokens and context variables.
Args:
expression (str): The expression to evaluate.
context (dict): A dictionary mapping variable names to their values, which
can be used in the expression.
allowed_tokens (list): A list of strings representing allowed tokens (such as
operators, function names, etc.) that can be used in the expression.
Returns:
any: The result of evaluating the expression.
Raises:
ValueError: If the expression contains tokens not in the allowed list or context keys.
Note:
This function should be used carefully, as it employs `eval`, which can
execute arbitrary code. The function attempts to mitigate security risks
by restricting the available tokens and not exposing built-in functions.
"""
allowed_sub_strings = list(context.keys()) + allowed_tokens
if is_made_of_sub_strings(expression, allowed_sub_strings):
return eval(expression, {"__builtins__": {}}, context)
raise ValueError(
f"The expression '{expression}' can not be evaluated because it contains tokens outside the allowed list of {allowed_sub_strings}."
)
|