Source code for speasy.core.algorithms

"""
.. 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")