# pylint: disable=missing-function-docstring """Global configuration for XGBoost""" import ctypes import json from contextlib import contextmanager from functools import wraps from typing import Any, Callable, Dict, Iterator, Optional, cast from ._typing import _F from .core import _LIB, _check_call, c_str, py_str def config_doc( *, header: Optional[str] = None, extra_note: Optional[str] = None, parameters: Optional[str] = None, returns: Optional[str] = None, see_also: Optional[str] = None, ) -> Callable[[_F], _F]: """Decorator to format docstring for config functions. Parameters ---------- header: str An introducion to the function extra_note: str Additional notes parameters: str Parameters of the function returns: str Return value see_also: str Related functions """ doc_template = """ {header} Global configuration consists of a collection of parameters that can be applied in the global scope. See :ref:`global_config` for the full list of parameters supported in the global configuration. {extra_note} .. versionadded:: 1.4.0 """ common_example = """ Example ------- .. code-block:: python import xgboost as xgb # Show all messages, including ones pertaining to debugging xgb.set_config(verbosity=2) # Get current value of global configuration # This is a dict containing all parameters in the global configuration, # including 'verbosity' config = xgb.get_config() assert config['verbosity'] == 2 # Example of using the context manager xgb.config_context(). # The context manager will restore the previous value of the global # configuration upon exiting. with xgb.config_context(verbosity=0): # Suppress warning caused by model generated with XGBoost version < 1.0.0 bst = xgb.Booster(model_file='./old_model.bin') assert xgb.get_config()['verbosity'] == 2 # old value restored Nested configuration context is also supported: Example ------- .. code-block:: python with xgb.config_context(verbosity=3): assert xgb.get_config()["verbosity"] == 3 with xgb.config_context(verbosity=2): assert xgb.get_config()["verbosity"] == 2 xgb.set_config(verbosity=2) assert xgb.get_config()["verbosity"] == 2 with xgb.config_context(verbosity=3): assert xgb.get_config()["verbosity"] == 3 """ def none_to_str(value: Optional[str]) -> str: return "" if value is None else value def config_doc_decorator(func: _F) -> _F: func.__doc__ = ( doc_template.format( header=none_to_str(header), extra_note=none_to_str(extra_note) ) + none_to_str(parameters) + none_to_str(returns) + none_to_str(common_example) + none_to_str(see_also) ) @wraps(func) def wrap(*args: Any, **kwargs: Any) -> Any: return func(*args, **kwargs) return cast(_F, wrap) return config_doc_decorator @config_doc( header=""" Set global configuration. """, parameters=""" Parameters ---------- new_config: Dict[str, Any] Keyword arguments representing the parameters and their values """, ) def set_config(**new_config: Any) -> None: not_none = {} for k, v in new_config.items(): if v is not None: not_none[k] = v config = json.dumps(not_none) _check_call(_LIB.XGBSetGlobalConfig(c_str(config))) @config_doc( header=""" Get current values of the global configuration. """, returns=""" Returns ------- args: Dict[str, Any] The list of global parameters and their values """, ) def get_config() -> Dict[str, Any]: config_str = ctypes.c_char_p() _check_call(_LIB.XGBGetGlobalConfig(ctypes.byref(config_str))) value = config_str.value assert value config = json.loads(py_str(value)) return config @contextmanager @config_doc( header=""" Context manager for global XGBoost configuration. """, parameters=""" Parameters ---------- new_config: Dict[str, Any] Keyword arguments representing the parameters and their values """, extra_note=""" .. note:: All settings, not just those presently modified, will be returned to their previous values when the context manager is exited. This is not thread-safe. """, see_also=""" See Also -------- set_config: Set global XGBoost configuration get_config: Get current values of the global configuration """, ) def config_context(**new_config: Any) -> Iterator[None]: old_config = get_config().copy() set_config(**new_config) try: yield finally: set_config(**old_config)