Source code for utilipy.config

# -*- coding: utf-8 -*-

# ----------------------------------------------------------------------------
#
# TITLE   : config
# PROJECT : utilipy
#
# ----------------------------------------------------------------------------

# Docstring and Metadata
"""Configuration settings for `utilipy`.

TODO
----
Adopt astropy affiliate package configuration style.

"""

__author__ = "Nathaniel Starkman"

__all__ = [
    "__config__",
    "_DEFAULT_CONFIG",
    "_DEFAULT_FILE",
    "check_config",
    "write_config",
    "get_import_verbosity",
    "set_import_verbosity",
    "use_import_verbosity",
    "get_warnings_verbosity",
    "set_warnings_verbosity",
    "use_warnings_verbosity",
    "get_frozen_constants",
    "set_frozen_constants",
    "use_frozen_constants",
    "cfilename",
]


##############################################################################
# IMPORTS

from typing import Union, Any, Optional, Dict
from typing_extensions import Literal
import os.path
from configparser import ConfigParser


##############################################################################
# DEFAULT CONFIGURATION

# The default configuration
_DEFAULT_CONFIG: Dict[str, Union[str, Dict[str, str]]] = {
    "verbosity": {"verbose-imports": "True", "warnings": "True"},
    "plot": {"seaborn-defaults": "False"},
    "util": {"frozen-constants": "True"},
}

_DEFAULT_FILE: str = os.path.join(os.path.expanduser("~"), ".utilipyrc")


##############################################################################
# PARAMETERS

__config__ = ConfigParser()


##############################################################################


[docs]def check_config(configuration: ConfigParser) -> bool: """Check that the configuration is a valid utilipy configuration. Parameters ---------- configuration: ConfigParser the configuration file Returns ------- bool whether the configuration is a valid utilipy configuration. """ sec_key: str for sec_key in _DEFAULT_CONFIG.keys(): # iter through expected keys # check if section exists if not configuration.has_section(sec_key): return False # check if options within section exist for key in _DEFAULT_CONFIG[sec_key]: if not configuration.has_option(sec_key, key): return False return True
# /def
[docs]def write_config( filename: str, configuration: Optional[ConfigParser] = None ) -> None: """Write configuration. Parameters ---------- filename: str configuration: ConfigParser, optional configuration to draw from defaults to `_DEFAULT_CONFIG` if not in `configuration` """ # Writes default if configuration is None writeconfig = ConfigParser() # Write different sections sec_key: str for sec_key in _DEFAULT_CONFIG.keys(): writeconfig.add_section(sec_key) for key in _DEFAULT_CONFIG[sec_key]: if configuration is None: writeconfig.set(sec_key, key, _DEFAULT_CONFIG[sec_key][key]) elif not configuration.has_section( sec_key ) or not configuration.has_option(sec_key, key): writeconfig.set(sec_key, key, _DEFAULT_CONFIG[sec_key][key]) else: writeconfig.set(sec_key, key, configuration.get(sec_key, key)) with open(filename, "w") as configfile: writeconfig.write(configfile) return None
# /def ############################################################################## # Set configuration variables on the fly
[docs]def get_import_verbosity() -> bool: """Get whether the full import information is printed or not.""" return __config__.getboolean("verbosity", "verbose-imports")
# /def
[docs]def set_import_verbosity( verbosity: Union[bool, Literal["True", "False"]] ) -> None: """Set whether the full import information is printed or not.""" assert str(verbosity) in {"True", "False"}, f"{str(verbosity)}" __config__.set("verbosity", "verbose-imports", str(verbosity)) return
# /def
[docs]class use_import_verbosity: """Docstring for use_import_verbosity.""" def __init__( self, verbosity: Union[bool, Literal["True", "False"]] ) -> None: """__init__.""" self.original_verbosity = get_import_verbosity() self.verbosity = verbosity return # /def def __enter__(self): """Enter with statement, using specified import verbosity.""" if self.verbosity is not None: set_import_verbosity(self.verbosity) return self # /def def __exit__(self, type: Any, value: Any, traceback: Any) -> None: """Exit with statement, restoring original import verbosity.""" # Exception handling here traceback # pragma: no cover set_import_verbosity(self.original_verbosity) return
# /def # ----------------------------------------------------------------------------
[docs]def get_warnings_verbosity() -> bool: """Get warnings verbosity.""" return __config__.getboolean("verbosity", "warnings")
# /def
[docs]def set_warnings_verbosity(key: Union[bool, str]) -> None: """Set warnings verbosity.""" assert str(key) in {"True", "False"} __config__.set("verbosity", "warnings", str(key)) return
# /def
[docs]class use_warnings_verbosity: """Docstring for use_warnings_verbosity.""" def __init__(self, verbosity: Optional[bool] = None) -> None: """__init__.""" self.original_state = get_warnings_verbosity() self.state = verbosity return # /def def __enter__(self) -> Any: """Enter with statement, using specified import verbosity.""" if self.state is not None: set_warnings_verbosity(self.state) return self # /def def __exit__(self, type, value, traceback) -> None: """Exit with statement, restoring original import verbosity.""" # Exception handling here set_warnings_verbosity(self.original_state) return
# /def # ----------------------------------------------------------------------------
[docs]def get_frozen_constants() -> bool: """Get warnings verbosity.""" return __config__.getboolean("util", "frozen-constants")
# /def
[docs]def set_frozen_constants(key: Union[bool, str]) -> None: """Set warnings verbosity.""" assert str(key) in {"True", "False"} __config__.set("util", "frozen-constants", str(key)) return
# /def
[docs]class use_frozen_constants: """docstring for use_frozen_constants.""" def __init__(self, frozen: Optional[bool] = None) -> None: """__init__.""" self.original_state = get_frozen_constants() self.state = frozen return # /def def __enter__(self) -> Any: """Enter with statement, using specified state.""" if self.state is not None: set_frozen_constants(self.state) return self # /def def __exit__(self, type, value, traceback) -> None: """Exit with statement, restoring original state.""" # Exception handling here set_frozen_constants(self.original_state) return
# /def ############################################################################## # RUNNING # Read the local configuration file cfilename = __config__.read(".utilipyrc") # if it doesn't exist if not cfilename: cfilename = __config__.read(_DEFAULT_FILE) # read default config if not cfilename: # no default config write_config(_DEFAULT_FILE) # make default config __config__.read(_DEFAULT_FILE) # and read in # check config is valid if not check_config(__config__): write_config(cfilename[-1], __config__) __config__.read(cfilename[-1]) ############################################################################## # END