Source code for topo_metrics.utils
from __future__ import annotations
import io
import logging
import os
import sys
import warnings
from typing import Any, Iterable
[docs]
class hushed:
"""
A context manager to suppress stdout and stderr.
Notes
-----
- I have made this as aggressive as possible to suppress all warnings and
logging messages. This is because the function `instantiate_julia`brings in
a lot of noise that irritates me.
"""
def __enter__(self):
assert sys.__stdout__ is not None
assert sys.__stderr__ is not None
self._stdout_fd = sys.__stdout__.fileno()
self._stderr_fd = sys.__stderr__.fileno()
self._saved_stdout_fd = os.dup(self._stdout_fd)
self._saved_stderr_fd = os.dup(self._stderr_fd)
self._devnull = open(os.devnull, "w")
os.dup2(self._devnull.fileno(), self._stdout_fd)
os.dup2(self._devnull.fileno(), self._stderr_fd)
# ALSO redirect Python-level output streams
self._saved_stdout_obj = sys.stdout
self._saved_stderr_obj = sys.stderr
sys.stdout = io.StringIO()
sys.stderr = io.StringIO()
warnings.simplefilter("ignore")
logging.disable(logging.CRITICAL)
return self
def __exit__(self, exc_type, exc_value, traceback):
os.dup2(self._saved_stdout_fd, self._stdout_fd)
os.dup2(self._saved_stderr_fd, self._stderr_fd)
os.close(self._saved_stdout_fd)
os.close(self._saved_stderr_fd)
self._devnull.close()
sys.stdout = self._saved_stdout_obj
sys.stderr = self._saved_stderr_obj
warnings.resetwarnings()
logging.disable(logging.NOTSET)
[docs]
def to_tuple(not_tuple: list | Any) -> Any:
"""
Recursively converts a list (or nested lists) to a tuple.
This function is designed to handle lists that may contain nested lists,
and it will recursively convert all levels of lists into tuples.
Parameters
----------
not_tuple
The input to be converted. If the input is a list, it will be
recursively converted to a tuple. Otherwise, it will be returned as-is.
Returns
-------
A tuple equivalent of the input list, or the original element if it is not a
list.
Example
-------
>>> totuple([1, 2, [3, 4, [5, 6]], 7])
(1, 2, (3, 4, (5, 6)), 7)
>>> totuple('string')
'string'
"""
if isinstance(not_tuple, str):
return not_tuple
if isinstance(not_tuple, Iterable):
return tuple(to_tuple(i) for i in not_tuple)
return not_tuple
[docs]
def min_count(x: list[int]) -> tuple[int, int]:
"""
Count the number of times the minimum value appears in the list `X`.
"""
x = list(x)
if not x:
raise ValueError("The list X cannot be empty")
min_value = min(x)
return min_value, x.count(min_value)