Source code for pycnfg.utils

"""The module includes auxiliary utilities."""


import atexit
import importlib
import os
import sys
import time
import warnings

import pycnfg


try:
    from winsound import Beep as Beep
except ImportError:
    def Beep(frequency=400, duration=2000):
        path = '/'.join(__file__.split('/')[:-1])
        os.system(f'aplay {path}/beep.wav')

__all__ = ['find_path', 'run']


[docs]def find_path(script_name=False, filepath=None): """Get full path to main script. Parameters ---------- script_name : bool, optional (default=False) If True, return also script name. filepath : str, optional (default=None) Path to main script. If None: get from sys.argv for standard interpreter, get from workdir for Ipython. If sys.argv empty, get from working directory. Returns ------- project_dir : str Full path to start script directory. script_name : str, optional if ``script_name`` is True Main script name. 'ipython' for Ipython. """ def is_ipython(): """Return True if ipython else False""" try: get_ipython = importlib.import_module('get_ipython', 'IPython') shell = get_ipython().__class__.__name__ if shell == 'ZMQInteractiveShell': # Jupyter notebook or qtconsole. return True elif shell == 'TerminalInteractiveShell': # Terminal running IPython. return True else: # Other type (?). return False except NameError: # Probably standard Python interpreter. return False except ModuleNotFoundError: # No IPython lib installed (check only if Terminal or standard). return "idlelib" not in sys.modules if filepath is not None: temp = filepath.replace('\\', '/').split('/') project_dir = '/'.join(temp[:-1]) script_name_ = temp[-1][:-3] elif is_ipython(): project_dir = os.getcwd().replace('\\', '/') script_name_ = 'ipython' else: # sys.argv provide script_name, but not work in Ipython. # For example ['path/run.py', '55']. ext_size = 3 # '.py' script_name_ = sys.argv[0]\ .replace('\\', '/')\ .split('/')[-1][:-ext_size] # run project_dir = sys.argv[0]\ .replace('\\', '/')[:-len(script_name_)-ext_size] print(f"Identified project dir:\n {project_dir}", flush=True) if script_name: return project_dir, script_name_ else: return project_dir
[docs]def run(cnfg, dcnfg=None, objects=None, oid=None, resolve_none=False, update_expl=False, mutable=False, beep=False, debug=False): """Wrapper over configuration handler. Parameters ---------- cnfg : dict or str Configuration to pass in ``pycnfg.Handler.read()``: {'section_id': {'configuration_id': configuration,}}. If str, absolute path to the file with ``CNFG`` variable or relative to work dir. dcnfg : dict, str, optional (default=None) Default configurations to pass in ``pycnfg.Handler.read()``. If str, absolute path to file with ``CNFG`` variable or relative to work dir. objects : dict, optional (default=None) Dict of initial objects to pass in ``pycnfg.Handler.exec()``: {'object_id': object}. If None, set {}. oid : str, optional (default=None) Unique identifier of ``cnfg``. If None, use ``str(time.time())``. resolve_none : bool, optional (default=False) If True, try to resolve None values for step kwargs. If kwarg name matches with section name, substitute either with conf_id on zero position or val, depending on if ``_id`` prefix in ``kwarg_name``. update_expl : bool, optional (default=True) If True apply ``global`` values to update explicitly set kwargs for target step, otherwise update only unset kwargs. mutable : bool, optional (default=False) If True, rewrite existed object when configuration id already in ``objects``. Otherwise skip execution and remain original. beep : bool, optional (default=False) If True, play sound notification on ending. debug : bool, optional (default=False) If True, print executed configuration. Returns ------- objects : dict Dict of objects created by execution all configurations: {'section_id__configuration_id': object}. Notes ----- ``cnfg`` could be executed as sub-configuration itself: * init = cnfg * steps = [('read', {..}), ('exec', {..})] * producer = pycnfg.Handler(objects, oid) objects[oid] = producer.run(init, steps) See Also -------- :class:`pycnfg.Handler`: Reads configurations, executes steps. """ warnings.simplefilter(action='ignore', category=FutureWarning) if objects is None: objects = {} if oid is None: oid = str(time.time()).replace('.', '-') if beep: atexit.register(Beep, 600, 500) atexit.register(Beep, 400, 2000) # Will be the first. handler = pycnfg.Handler(objects, oid) configs = handler.read(cnfg, dcnfg=dcnfg, resolve_none=resolve_none, update_expl=update_expl) objects = handler.exec(configs, mutable=mutable, debug=debug) return objects
if __name__ == '__main__': pass