Source code for fastcfg

"""
FastCFG - Modern configuration management for Python applications.

Created by Josh Breidinger (2025)
Author: Josh Breidinger
Email: company@breisoft.com
GitHub: https://github.com/breisoft

Born from the frustration of serverless configuration hell,
FastCFG makes config management simple, fast, and reliable.
"""

from fastcfg.config.cfg import Config

# Global config object
config = Config()

import threading
from typing import Any, Callable, Optional, Union

from fastcfg.config.cfg import AbstractConfigItem


[docs] def refresh(target: Union[Config, AbstractConfigItem]): """ Manually refresh a Config or ConfigItem to detect external changes. Args: target: Config object or ConfigItem to refresh Example: # In your own loop for _ in range(60): refresh(config.my_var) # Triggers change detection time.sleep(1) """ if isinstance(target, Config): for key in target.keys(): _ = getattr(target, key, None) else: _ = target.value
[docs] def needs_value( func: Callable[..., Any], config_value: Any, *args: Any, verbose: bool = False, **kwargs: Any, ) -> Optional[bool]: """ Test whether a function requires explicit .value access or works with FastCFG magic. This helper function determines if you can pass a FastCFG config value directly to a function, or if you need to use .value to extract the underlying value. This is particularly useful for identifying C extensions that require exact types. Args: func: The function to test compatibility with config_value: A FastCFG wrapped value (e.g., config.port) *args: Additional positional arguments to pass to func (after config_value) verbose: If True, prints diagnostic information about the test **kwargs: Keyword arguments to pass to func Returns: bool or None: - False: Function works with FastCFG magic (no .value needed) - True: Function requires .value to be called on config_value - None: Function doesn't work even with .value (incompatible) Example: config.size = 10 # Check if np.zeros needs .value if needs_value(np.zeros, config.size): arr = np.zeros(config.size.value) else: arr = np.zeros(config.size) # With verbose output for debugging needs_value(np.zeros, config.size, verbose=True) # Prints: zeros requires .value - use config.size.value """ func_name: str = getattr(func, "__name__", str(func)) # First, try calling the function with the FastCFG magic value directly try: # Build arguments with config_value first, then any additional args test_args: tuple[Any, ...] = (config_value,) + args func(*test_args, **kwargs) # Success - the function works with our magic wrapper if verbose: print(f"{func_name} works with FastCFG magic - no .value needed") return False except TypeError: # The function rejected our ValueWrapper, try with .value try: test_args = (config_value.value,) + args func(*test_args, **kwargs) # Success with .value if verbose: attr_name: str = getattr( config_value._item, "name", "config_value" ) print( f"{func_name} requires .value - use config.{attr_name}.value" ) return True except Exception as e: # Function doesn't work even with .value if verbose: print( f"{func_name} appears incompatible: {type(e).__name__}: {e}" ) return None except Exception as e: # Some other error occurred if verbose: print( f"{func_name} failed with unexpected error: {type(e).__name__}: {e}" ) return None