"""
.. testsetup:: *
from speasy.core.algorithms import *
import numpy as np
"""
import random
from typing import Any, Dict, Callable
from functools import wraps
"""
The rationale behind the following function is to randomize the order of execution so we minimize the requests collisions and maximize the throughput.
"""
[docs]
def randomized_map(f: Callable, l, *args, **kwargs):
"""Applies function f to all elements in list l in a randomized order
Parameters
----------
f: Callable
function to apply to each element in l
l: list
list of elements to process
args: Any
additional positional arguments to pass to f
kwargs: Any
additional keyword arguments to pass to f
Returns
-------
list
A list with the results of applying f to each element in l, in the original order
Examples
--------
>>> randomized_map(lambda x: x**2, [1,2,3,4])
[1, 4, 9, 16]
"""
if not len(l):
return []
indexed_list = list(enumerate(l))
random.shuffle(indexed_list)
result = sorted([(i, f(e, *args, **kwargs)) for i, e in indexed_list], key=lambda x: x[0])
return [e for i, e in result]
[docs]
def pack_kwargs(**kwargs: Any) -> Dict:
"""Packs given keyword arguments into a dictionary
Parameters
----------
kwargs: Any
Any keyword argument is accepted
Returns
-------
dict
A dict with all kwargs packed
Examples
--------
>>> pack_kwargs(a=1, b="2")
{'a': 1, 'b': '2'}
"""
return kwargs
[docs]
class AllowedKwargs(object):
"""A decorator that prevent from passing unexpected kwargs to a function
"""
def __init__(self, allowed_list):
self.allowed_list = set(allowed_list)
def __call__(self, func):
@wraps(func)
def wrapped(*args, **kwargs):
unexpected_args = list(
filter(lambda arg_name: arg_name not in self.allowed_list, kwargs.keys()))
if not unexpected_args:
return func(*args, **kwargs)
raise TypeError(
f"Unexpected keyword argument {unexpected_args}, allowed keyword arguments are {self.allowed_list}")
return wrapped
[docs]
def fix_name(name: str):
"""Makes given input compatible with python charset https://docs.python.org/3/reference/lexical_analysis.html#identifiers
Parameters
----------
name: str
input string to sanitize
Returns
-------
str
a string compatible with python naming rules
Examples
--------
>>> fix_name('Parker Solar Probe (PSP)')
'Parker_Solar_Probe_PSP'
>>> fix_name('IS⊙ISEPI_Lo')
'ISoISEPI_Lo'
>>> fix_name('all_Legal_strings_123')
'all_Legal_strings_123'
"""
rules = (
('-', '_'),
(':', '_'),
('.', '_'),
('(', ''),
(')', ''),
('/', ''),
(' ', '_'),
('{', ''),
('}', ''),
('(', ''),
('⊙', 'o'),
(';', '_'),
(',', '_'),
('%', '_')
)
if len(name):
if name[0].isnumeric():
name = "n_" + name
for bad, replacement in rules:
if bad in name:
name = name.replace(bad, replacement)
return name
raise ValueError("Got empty name")