parameterspace.utils
extract_lambda_information(source_lines)
[summary]
Parameters:
Name | Type | Description | Default |
---|---|---|---|
source_lines |
Iterable |
[description] |
required |
Exceptions:
Type | Description |
---|---|
RuntimeError |
If function definition is not a valid Lambda function. |
Returns:
Type | Description |
---|---|
Tuple[list, str] |
[description] |
Source code in parameterspace/utils.py
def extract_lambda_information(source_lines: Iterable) -> Tuple[list, str]:
"""[summary]
Args:
source_lines: [description]
Raises:
RuntimeError: If function definition is not a valid Lambda function.
Returns:
[description]
"""
condensed_code = "".join(source_lines).replace(os.linesep, "") # join lines
condensed_code = " ".join(
condensed_code.split()
) # replace multiple spaces by a single one
try:
signature, body = condensed_code.split("lambda")[1].split(":")
except IndexError as e:
raise RuntimeError(
"The function definition does not look like a valid Lambda function:\n"
+ "".join(source_lines)
) from e
while len(body) > 1:
lambda_def = f"lambda {signature}: {body}"
try:
_ = compile(lambda_def, "<unused filename>", "eval")
break
except SyntaxError:
body = body[:-1]
variables = [s.strip() for s in signature.split(",")]
return variables, body.strip().rstrip(",")
store_init_arguments(init_method)
Stores init arguments (including keyword arguments) and auto converts
numpy.ndarray
s to list
s for json serializability.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
init_method |
Callable |
[description] |
required |
Returns:
Type | Description |
---|---|
Callable |
[description] |
Source code in parameterspace/utils.py
def store_init_arguments(init_method: Callable) -> Callable:
"""Stores init arguments (including keyword arguments) and auto converts
`numpy.ndarray`s to `list`s for json serializability.
Args:
init_method: [description]
Returns:
[description]
"""
@wraps(init_method)
def wrapper(self, *args, **kwargs):
args = [a.tolist() if isinstance(a, np.ndarray) else a for a in args]
for k, k_value in kwargs.items():
if isinstance(k_value, np.ndarray):
kwargs[k] = k_value.tolist()
self._init_args = args
self._init_kwargs = kwargs
init_method(self, *args, **kwargs)
return wrapper
verify_lambda(variables, body)
Check serialized lambda expression for malicious code.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
variables |
List[str] |
List of the variable names used in the function body. |
required |
body |
str |
Function body string representation to check for allowed expressions. |
required |
Returns:
Type | Description |
---|---|
bool |
True if the function body is considered safe. |
Source code in parameterspace/utils.py
def verify_lambda(variables: List[str], body: str) -> bool:
"""Check serialized lambda expression for malicious code.
Args:
variables: List of the variable names used in the function body.
body: Function body string representation to check for allowed expressions.
Returns:
True if the function body is considered safe.
"""
if len(body) > 200:
return False
if "eval(" in body:
return False
forbidden_characters = "\\;"
for c in forbidden_characters:
if c in body:
return False
allowed_characters = ".,0123456789+-*/()<=!> "
allowed_functions = [
"math.sin",
"math.cos",
"math.exp",
"math.log",
"or",
"and",
"not",
"in",
]
for vn in variables:
body = body.replace(vn, "")
for fn in allowed_functions:
body = body.replace(fn, "")
for c in allowed_characters:
body = body.replace(c, "")
# remove all single quoted strings
matches = re.findall(r"\'(.+?)\'", body)
for m in matches:
body = body.replace("'" + m + "'", "")
# remove all double quoted strings
matches = re.findall(r"\"(.+?)\"", body)
for m in matches:
body = body.replace('"' + m + '"', "")
if len(body) > 0:
print("body:", body)
return False
return True