""" Miscellaneous utilities. """ from collections import abc from functools import lru_cache from typing import Any from numpy import isnan def astype_if(value: Any, type_: type | None) -> Any: """Convert value to type_ if it is not None. Args: value (Any): Value to convert. type_ (type): Type to convert value to. If None, returned value will be None. Returns: Any: Value converted to type_ if it is not None. Example: >>> astype_if("3", int) 3 >>> astype_if(None, int) is None True """ if type_ is None or value is None: return None return type_(value) @lru_cache(maxsize=1024) def is_nan(value: abc.Hashable) -> bool: """Check if value is NaN. Args: value (Hashable): Value to check. Must be hashable for leveraging LRU cache. Returns: bool: True if value is NaN, False otherwise. """ return is_nan_no_cache(value) def is_nan_no_cache(value: Any) -> bool: """Check if value is NaN. This function does not use LRU cache and thus is slower than is_nan(), but can be used for non-hashable values. Args: value (Hashable): Value to check. Returns: bool: True if value is NaN, False otherwise. """ try: return isnan(value) except TypeError: return False def load_env(env_file_path: str) -> dict[str, str]: """Load environment variables from a file. This could be done via a third-party library like python-dotenv, but we're keeping it simple and using a custom implementation for security reasons (keeping the codebase as lean as possible and avoiding unnecessary dependencies). Args: env_file_path (str, optional): Path to the environment file. Returns: dict[str, str]: Environment variables. """ env_vars = {} with open(env_file_path, "r", encoding="utf-8") as file: for line in file: # Ignore comments and empty/whitespace-only lines stripped_line = line.strip() if stripped_line and not stripped_line.startswith("#"): # Split only on the first "=" to correctly handle values with "=" in them parts = stripped_line.split("=", 1) try: key, value = parts except ValueError: continue env_vars[key.strip()] = value.strip() return env_vars