Source code for pyecsca.misc.utils
"""Just some utilities I promise."""
import sys
from ast import parse
from contextlib import contextmanager
from typing import List, Any, Generator
from ..misc.cfg import getconfig, TemporaryConfig
from concurrent.futures import ProcessPoolExecutor, as_completed, Future
[docs]
def pexec(s):
return parse(s, mode="exec")
[docs]
def peval(s):
return parse(s, mode="eval")
[docs]
def in_notebook() -> bool:
"""Test whether we are executing in Jupyter notebook."""
try:
from IPython import get_ipython
if "IPKernelApp" not in get_ipython().config: # pragma: no cover
return False
except ImportError:
return False
except AttributeError:
return False
return True
[docs]
def log(*args, **kwargs):
"""Log a message."""
if in_notebook() and getconfig().log.enabled:
print(*args, **kwargs)
[docs]
def warn(*args, **kwargs):
"""Log a message."""
if in_notebook() and getconfig().log.enabled:
print(*args, **kwargs, file=sys.stderr)
[docs]
@contextmanager
def silent():
"""Temporarily disable output."""
with TemporaryConfig() as cfg:
cfg.log.enabled = False
yield
[docs]
class TaskExecutor(ProcessPoolExecutor):
"""A simple ProcessPoolExecutor that keeps tracks of tasks that were submitted to it."""
keys: List[Any]
futures: List[Future]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.keys = []
self.futures = []
[docs]
def submit_task(self, key: Any, fn, /, *args, **kwargs):
future = self.submit(fn, *args, **kwargs)
self.futures.append(future)
self.keys.append(key)
return future
@property
def tasks(self):
return list(zip(self.keys, self.futures))
[docs]
def as_completed(self) -> Generator[tuple[Any, Future], Any, None]:
for future in as_completed(self.futures):
i = self.futures.index(future)
yield self.keys[i], future
self.futures = []
self.keys = []