Skip to content

Reference

utils_mystuff

Package with various utils i.e. VB regex translation, CLI logging, file handling, ...

Set of submodules contains:

  • submodule for converting Microsoft VB /COM type regular expression to Python regular expression
  • submodule with utilities to log CLI calls of Python scripts
  • submodule with utilities for file handling
  • submodule with wrapper for basic GUI functions for various GUI frameworks
  • submodule with various utilities - read config file with standard parser, set up standard logger object ...

Raises:

Type Description
ImportError

import error if implementation is not available for platform

GUIwrapper = GUIwrapperClass() module-attribute

LOCALE_LOCK = threading.Lock() module-attribute

err_msg = f'No implementation for your platform ('{os.name}') available' module-attribute

loggerCLI = setup_CLI_logger(loggerNameCLIlog) module-attribute

loggerNameCLIlog = 'Log_Python_CLI' module-attribute

loggers: dict[str, logging.Logger] = {} module-attribute

parserinfo_localized(localeID: str, *args, **kwargs)

parserinfo_localized - create localized date parser object

Source code in src/utils_mystuff/utils_various.py
def __init__(self, localeID: str, *args, **kwargs):
    """ initialize parserinfo localized """

    with setlocale(localeID):
        self.WEEKDAYS = zip(calendar.day_abbr, calendar.day_name)  # type: ignore[assignment]
        self.MONTHS = list(zip(calendar.month_abbr, calendar.month_name))[1:]  # type: ignore[assignment]
    super().__init__(*args, **kwargs)

MONTHS = list(zip(calendar.month_abbr, calendar.month_name))[1:] instance-attribute

WEEKDAYS = zip(calendar.day_abbr, calendar.day_name) instance-attribute

alertbox(text: str, title: str = '') -> None

alertbox - caller stub for singleton GUIwrapperClass object method

Parameters:

Name Type Description Default
text str

prompt text

required
title str

title for popup. Defaults to empty string.

''
Source code in src/utils_mystuff/utils_GUI.py
def alertbox(text: str, title: str = "") -> None:
    """
    alertbox - caller stub for singleton GUIwrapperClass object method

    Args:
        text (str): prompt text
        title (str): title for popup. Defaults to empty string.
    """
    GUIwrapper.alertbox(text, title)

clean_for_eval(expression: str) -> str

clean_for_eval - clean regular expression after substitution

delete leading zeros from integer constants to overcome eval() error

Parameters:

Name Type Description Default
expression str

regular expression to be cleaned

required

Returns:

Name Type Description
str str

cleaned regular expression

Source code in src/utils_mystuff/convert_regex.py
def clean_for_eval(expression: str) -> str:
    """
    clean_for_eval - clean regular expression after substitution

    delete leading zeros from integer constants to overcome eval() error

    Arguments:
        expression (str): regular expression to be cleaned

    Returns:
        str: cleaned regular expression
    """

    operator_char = [" ", "<", "=", ">", "+", "-", "*", "/", "%", "("]

    find_start = 0
    for char in operator_char:
        pos = expression.find(f"{char}0")
        while pos >= 0:
            if expression[pos + 2:pos + 3] in "0123456789":
                expression = expression[0:pos + 1] + expression[pos + 2:]
                find_start = pos
            else:
                find_start = pos + 1
            pos = expression.find(f"{char}0", find_start)

    return expression

close_app_file(filename: str, msg: str, title: str) -> None

close_app_file - close data file opened by an application

Parameters:

Name Type Description Default
filename str

filename

required
msg str

message for alert box

required
title str

title for alert box

required
Source code in src/utils_mystuff/utils_filehandling.py
def close_app_file(filename: str, msg: str, title: str) -> None:
    """
    close_app_file - close data file opened by an application

    Args:
        filename (str): filename
        msg (str): message for alert box
        title (str): title for alert box
    """

    close_app_windowtitle(filename)
    if file_locked(filename):
        close_app_windowtitle(os.path.splitext(os.path.basename(filename))[0])
    while file_locked(filename):
        alertbox(msg, title)

confirmYesNo(text: str, title: str = '', buttons: list = ['Yes', 'No']) -> str

confirmYesNo - caller stub for singleton GUIwrapperClass object method

Parameters:

Name Type Description Default
text str

prompt text

required
title str

title for popup. Defaults to empty string.

''
buttons list

label for buttons. Defaults to ['Yes', 'No'].

['Yes', 'No']

Returns:

Name Type Description
str str

label of pressed button

Source code in src/utils_mystuff/utils_GUI.py
def confirmYesNo(text: str, title: str = "", buttons: list = ['Yes', 'No']) -> str:
    """
    confirmYesNo - caller stub for singleton GUIwrapperClass object method

    Args:
        text (str): prompt text
        title (str): title for popup. Defaults to empty string.
        buttons (list): label for buttons. Defaults to ['Yes', 'No'].

    Returns:
        str: label of pressed button
    """
    return GUIwrapper.confirmYesNo(text, title, buttons)

confirm_yes_no(text: str, title: str = '', buttons: list = ['Yes', 'No']) -> str

confirm_yes_no - caller stub for singleton GUIwrapperClass object method

Parameters:

Name Type Description Default
text str

prompt text

required
title str

title for popup. Defaults to empty string.

''
buttons list

label for buttons. Defaults to ['Yes', 'No'].

['Yes', 'No']

Returns:

Name Type Description
str str

label of pressed button

Source code in src/utils_mystuff/utils_GUI.py
def confirm_yes_no(text: str, title: str = "", buttons: list = ['Yes', 'No']) -> str:
    """
    confirm_yes_no - caller stub for singleton GUIwrapperClass object method

    Args:
        text (str): prompt text
        title (str): title for popup. Defaults to empty string.
        buttons (list): label for buttons. Defaults to ['Yes', 'No'].

    Returns:
        str: label of pressed button
    """
    return confirmYesNo(text, title, buttons)

convertRegExVB2Python(reVB: str) -> str

convertRegExVB2Python - convert Microsoft VB / COM regular expression to Python regular expression

Problem: syntax for regular expressions in the Microsoft VB / COM standard is different from Python.

Differences in the area of the standard syntax:

  • for group replacements notation is \n instead $n

Differences if regular expressions are used together with Eval():

  • different numerical value for True: VB environment = -1, Python = 1 -> boolean expressions need to be adjusted
  • string concatenation is '&' in VB and '+' in Python assumption: '+' is not used for source expressions even allowed
  • '+' may not be applied on int/str in Python -> numerical expressions must be bracketed in str()
  • language functions are to be replaced. Implemented: "Format" for numerical values

Parameters:

Name Type Description Default
reVB str

regular expression according to VB / COM standard for Microsoft RegEx engine

required

Returns:

Name Type Description
str str

converted regular expression for Python RegEx engine

Source code in src/utils_mystuff/convert_regex.py
def convertRegExVB2Python(reVB: str) -> str:
    """
    convertRegExVB2Python - convert Microsoft VB / COM regular expression to Python regular expression

    Problem: syntax for regular expressions in the Microsoft VB / COM standard is different from Python.

    Differences in the area of the standard syntax:

    - for group replacements notation is \\n instead $n

    Differences if regular expressions are used together with Eval():

    - different numerical value for True: VB environment = -1, Python = 1
      -> boolean expressions need to be adjusted
    - string concatenation is '&' in VB and '+' in Python
      assumption: '+' is not used for source expressions even allowed
    - '+' may not be applied on int/str in Python
      -> numerical expressions must be bracketed in str()
    - language functions are to be replaced. Implemented:
      "Format" for numerical values

    Arguments:
        reVB (str): regular expression according to VB / COM standard for Microsoft RegEx engine

    Returns:
        str: converted regular expression for Python RegEx engine
    """

    def split_terms(regex: str, quotemark, delim: str = "&+") -> list[str]:

        terms: list[str] = []
        regex_idx: int = 0
        term_start: int = 0
        quotemark_cnt: int = 0
        bracket_cnt: int = 0

        regex += " "
        while regex_idx < len(regex):
            if regex[regex_idx] == quotemark:
                quotemark_cnt += 1
            elif regex[regex_idx] in "(){}[]":
                bracket_cnt += 1
            elif (
                (regex[regex_idx] in delim or regex_idx >= len(regex) - 1) and
                quotemark_cnt % 2 == 0 and
                bracket_cnt % 2 == 0
            ):
                term = regex[term_start:regex_idx].strip()
                if (term[-1] in quotemark) or (terms[-1][-1] in quotemark) or (term.lower().find("format(") >= 0):
                    terms.append(term)
                else:
                    terms[-1] = terms[-1] + "+" + term
                term_start = regex_idx + 1
            regex_idx += 1

        return terms

    def convert_other(term: str, embedstr: bool = True) -> str:

        compare_operator = [">", "<", "="]
        foundbool = False

        term_idx = 0
        while term_idx < len(term):
            if term[term_idx] in compare_operator:
                if term[term_idx:term_idx + 1] == "<>":
                    term = term[:term_idx] + "!=" + term[term_idx + 2:]
                if term[term_idx:term_idx + 1] == "=":
                    term = term[:term_idx] + "==" + term[term_idx + 1:]
                    term_idx += 1
                while term[term_idx] != ")" and term_idx < len(term):
                    term_idx += 1
                if term[term_idx] == ")":
                    term = term[0:term_idx] + ")*-1" + term[term_idx + 1:]
                    term_idx += 3
                    foundbool = True
                elif term_idx == len(term):
                    term = "(" + term + ")*-1"
                    foundbool = True
            term_idx += 1

        if foundbool:
            term = term.replace("*-1*1", "*-1").replace("*-1*-1", "*1")

        if embedstr:
            return "str(" + term + ")"
        else:
            return term

    def convert_term(term: str, quotemark) -> str:

        if term[0] == quotemark:
            return term
        elif term.lower()[0:len("format(")] == "format(":
            # only simple integer formatting accepted
            params = term[len("format") + 1:len(term) - 1].split(",")
            params[0] = convert_other(params[0], False)
            return f"\"{{:0{params[1].count('0')}d}}\".format({params[0]})"
        else:
            return convert_other(term)

    # check quotation mark -> RegEx for use with Eval()
    if reVB[0] == "'":
        quotemark = "'"
    elif reVB[0] == "\"":
        quotemark = "\""
    else:
        quotemark = ""

    if quotemark != "":
        # top-level split of  regular expression into string terms
        terms = split_terms(reVB, quotemark)
        rePy = ""
        for term in terms:
            rePy = convert_term(term, quotemark) if rePy == "" else rePy + " + " + convert_term(term, quotemark)
    else:
        rePy = reVB

    # replace groups
    for grp_idx in range(9, 0, -1):
        rePy = rePy.replace(f"${grp_idx}", rf"\{grp_idx}")

    return rePy

convert_regexVB2python(reVB: str) -> str

convert_regexVB2python - convert Microsoft VB / COM regular expression to Python regular expression

Alternative caller for convertRegExVB2Python. See details there.

Parameters:

Name Type Description Default
reVB str

regular expression according to VB / COM standard for Microsoft RegEx engine

required

Returns:

Name Type Description
str str

converted regular expression for Python RegEx engine

Source code in src/utils_mystuff/convert_regex.py
def convert_regexVB2python(reVB: str) -> str:
    """
    convert_regexVB2python - convert Microsoft VB / COM regular expression to Python regular expression

    Alternative caller for convertRegExVB2Python. See details there.

    Arguments:
        reVB (str): regular expression according to VB / COM standard for Microsoft RegEx engine

    Returns:
        str: converted regular expression for Python RegEx engine
    """

    return convertRegExVB2Python(reVB)

convert_regexVB_2_python(reVB: str) -> str

convert_regexVB_2_python - convert Microsoft VB / COM regular expression to Python regular expression

Alternative caller for convertRegExVB2Python. See details there.

Parameters:

Name Type Description Default
reVB str

regular expression according to VB / COM standard for Microsoft RegEx engine

required

Returns:

Name Type Description
str str

converted regular expression for Python RegEx engine

Source code in src/utils_mystuff/convert_regex.py
def convert_regexVB_2_python(reVB: str) -> str:
    """
    convert_regexVB_2_python - convert Microsoft VB / COM regular expression to Python regular expression

    Alternative caller for convertRegExVB2Python. See details there.

    Arguments:
        reVB (str): regular expression according to VB / COM standard for Microsoft RegEx engine

    Returns:
        str: converted regular expression for Python RegEx engine
    """

    return convertRegExVB2Python(reVB)

copy_dictfields(source: dict, target: Any) -> None

copy_dict_fields - copy fields from dict to target structure

can be used to copy same named fields to a data class from TypedArgParser via .as_dict() or one dataclass to another via .asdict()

Parameters:

Name Type Description Default
source dict

source dictionary

required
target Any

target dictionary

required
Source code in src/utils_mystuff/utils_various.py
def copy_dictfields(source: dict, target: Any) -> None:
    """
    copy_dict_fields - copy fields from dict to target structure

    can be used to copy same named fields to a data class from TypedArgParser via <TypedArgParser object>.as_dict() or
    one dataclass to another via <dataclass>.asdict()

    Args:
        source (dict): source dictionary
        target (Any): target dictionary
    """
    copy_dictfields(source, target)

copydictfields(source: dict, target: Any) -> None

copydictfields - copy fields from dict to target structure

can be used to copy same named fields to a data class from TypedArgParser via .as_dict() or one dataclass to another via .asdict()

Parameters:

Name Type Description Default
source dict

source dictionary

required
target Any

target dictionary

required
Source code in src/utils_mystuff/utils_various.py
def copydictfields(source: dict, target: Any) -> None:
    """
    copydictfields - copy fields from dict to target structure

    can be used to copy same named fields to a data class from TypedArgParser via <TypedArgParser object>.as_dict() or
    one dataclass to another via <dataclass>.asdict()

    Args:
        source (dict): source dictionary
        target (Any): target dictionary
    """

    for key, value in source.items():
        if hasattr(target, key):
            target.key = value
        elif isinstance(target, dict):
            if key in target:
                target[key] = value

exitFinished(title: str = '') -> None

exitFinished - dummy finished message box.

Parameters:

Name Type Description Default
title str

title for message box. Defaults to empty string.

''
Source code in src/utils_mystuff/utils_GUI.py
def exitFinished(title: str = "") -> None:
    """
    exitFinished - dummy finished message box.

    Args:
        title (str): title for message box. Defaults to empty string.
    """
    msg: str = "Fertig."

    GUIwrapper.alertbox(msg, title)

exit_finished(title: str = '') -> None

exit_finished - dummy finished message box.

Parameters:

Name Type Description Default
title str

title for message box. Defaults to empty string.

''
Source code in src/utils_mystuff/utils_GUI.py
def exit_finished(title: str = "") -> None:
    """
    exit_finished - dummy finished message box.

    Args:
        title (str): title for message box. Defaults to empty string.
    """
    exitFinished(title)

file_locked(filepath: str, waittime: float = 0.1) -> bool

file_locked - check if file is locked

Parameters:

Name Type Description Default
filepath str

file to be checked

required
waittime float

waiting time for check, defaults to 0.1.

0.1

Returns:

Name Type Description
bool bool

lock indicator

Source code in src/utils_mystuff/utils_filehandling.py
def file_locked(filepath: str, waittime: float = 0.1) -> bool:
    """
    file_locked - check if file is locked

    Args:
        filepath (str): file to be checked
        waittime (float, optional): waiting time for check, defaults to 0.1.

    Returns:
        bool: lock indicator
    """

    if not (os.path.exists(filepath)):
        return False
    try:
        f = open(filepath, 'r')
        f.close()
    except OSError:
        return True

    lockfile = filepath + ".lckchk"
    if os.path.exists(lockfile):
        os.remove(lockfile)
    try:
        os.rename(filepath, lockfile)
        time.sleep(waittime)
        os.rename(lockfile, filepath)
        return False
    except OSError:
        return True

find_last_changed_file(searchpath: str, searchpattern: str, searchstart: Optional[datetime.datetime] = None, timeout_sec: int = 10) -> str

find_last_changed_file - find latest changed file in searchpath matching filename pattern provided as searchpattern

Parameters:

Name Type Description Default
searchpath str

path to search in

required
searchpattern str

file pattern

required
searchstart datetime

search for files changed after 'searchstart' only. Defaults to None.

None
timeout_sec int

timeout period. Defaults to 10.

10

Returns:

Name Type Description
str str

name of file found (if any)

Source code in src/utils_mystuff/utils_filehandling.py
def find_last_changed_file(
    searchpath: str,
    searchpattern: str,
    searchstart: Optional[datetime.datetime] = None,
    timeout_sec: int = 10
) -> str:
    """
    find_last_changed_file - find latest changed file in searchpath matching filename pattern provided as searchpattern

    Args:
        searchpath (str): path to search in
        searchpattern (str): file pattern
        searchstart (datetime.datetime, optional): search for files changed after 'searchstart' only. Defaults to None.
        timeout_sec (int, optional): timeout period. Defaults to 10.

    Returns:
        str: name of file found (if any)
    """

    timenow = datetime.datetime.now(dateutil.tz.tz.tzlocal())
    if searchstart is None:
        searchstart = timenow - datetime.timedelta(seconds=5)
    if searchstart.tzinfo is None:
        searchstart = pytz.utc.localize(searchstart)
    lastchangedfile = ""
    # lastchangedtimestamp = searchstart - datetime.timedelta(seconds=1)
    lastchangedtimestamp = searchstart.timestamp() - 1

    while (lastchangedfile == "") and (datetime.datetime.now(dateutil.tz.tz.tzlocal()) <= timenow + datetime.timedelta(seconds=timeout_sec)):

        with os.scandir(searchpath) as searchpathscan:
            scanentry: os.DirEntry    # overcome PyCharm IDE error - workaround derived from https://youtrack.jetbrains.com/issue/PY-46041
            for scanentry in searchpathscan:
                if fnmatch.fnmatch(scanentry.name, searchpattern):
                    filemodified = scanentry.stat().st_mtime_ns / 1000000000
                    if filemodified >= searchstart.timestamp():
                        pathfilename = os.path.join(searchpath, scanentry.name)
                        while os.path.isfile(pathfilename) and is_file_locked(pathfilename):
                            time.sleep(0.5)
                        if os.path.isfile(pathfilename) and not is_file_locked(pathfilename):
                            if filemodified > lastchangedtimestamp and scanentry.stat().st_size > 0:
                                lastchangedfile = scanentry.name
                                lastchangedtimestamp = filemodified
        searchpathscan.close()

    return lastchangedfile

get_real_apppath() -> tuple[str, str]

get_real_apppath - find true application directory for frozen/bundled execution

Returns:

Name Type Description
str tuple[str, str]

application path

Source code in src/utils_mystuff/utils_various.py
def get_real_apppath() -> tuple[str, str]:
    """
    get_real_apppath - find true application directory for frozen/bundled execution

    Returns:
        str: application path
    """

    if getattr(sys, 'frozen', False):
        application_path = os.path.dirname(sys.executable)
        running_mode = 'Frozen/executable'
    else:
        try:
            app_full_path = os.path.realpath(__file__)
            application_path = os.path.dirname(app_full_path)
            running_mode = "Non-interactive (e.g. 'python myapp.py')"
        except NameError:
            application_path = os.getcwd()
            running_mode = 'Interactive'

    return application_path, running_mode

ignore_exceptions(func: Callable[..., Any]) -> Callable[..., Any]

ignore_exceptions - decorator for ignoring exceptions using parameter in decorated function

Parameters:

Name Type Description Default
func Callable

function to be decorated

required

Returns:

Name Type Description
Callable Callable[..., Any]

wrapped function

Source code in src/utils_mystuff/utils_various.py
def ignore_exceptions(func: Callable[..., Any]) -> Callable[..., Any]:
    """
    ignore_exceptions - decorator for ignoring exceptions using parameter in decorated function

    Args:
        func (Callable): function to be decorated

    Returns:
        Callable: wrapped function
    """

    @wraps(func)
    def wrapper(*args, **kwargs):
        result = None
        ignored_exceptions = kwargs.get('ignored_exceptions')
        # if ignored_exceptions:
        if isinstance(ignored_exceptions, tuple) and all(issubclass(e, BaseException) for e in ignored_exceptions):
            try:
                result = func(*args, **kwargs)
            except ignored_exceptions:
                pass
        else:
            result = func(*args, **kwargs)
        return result

    return wrapper

ignore_exceptions_parameterized(ignored_exceptions: tuple[type[BaseException]]) -> Callable[[Callable[_P, _R]], Callable[_P, Optional[_R]]]

ignore_exceptions_parameterized - parameterized decorator for ignoring exceptions using closure

Parameters:

Name Type Description Default
ignored_exceptions tuple[BaseException]

exceptions to be ignored

required

Returns:

Name Type Description
Callable Callable[[Callable[_P, _R]], Callable[_P, Optional[_R]]]

wrapped function

Source code in src/utils_mystuff/utils_various.py
def ignore_exceptions_parameterized(ignored_exceptions: tuple[type[BaseException]]) -> Callable[[Callable[_P, _R]], Callable[_P, Optional[_R]]]:  # type: ignore
    """
    ignore_exceptions_parameterized - parameterized decorator for ignoring exceptions using closure

    Args:
        ignored_exceptions (tuple[BaseException]): exceptions to be ignored

    Returns:
        Callable: wrapped function
    """
    def ignore_exceptions_helper(func):

        @wraps(func)
        def wrapper(*args, **kwargs):
            result = None
            if ignored_exceptions:
                try:
                    result = func(*args, **kwargs)
                except ignored_exceptions:
                    pass
            else:
                result = func(*args, **kwargs)
            return result

        return wrapper

    return ignore_exceptions_helper

initLogger(loggername: str, formatstr: str = '%(asctime)s\t%(levelname)s\t%(message)s', datefmtstr: str = '%d.%m.%Y %H:%M:%S', filename: str = '') -> logging.Logger

initLogger - initialize standard logger object

Parameters:

Name Type Description Default
loggername str

name of logger

required
formatstr str

format string for log entries. Defaults to "%(asctime)s %(levelname)s %(message)s".

'%(asctime)s\t%(levelname)s\t%(message)s'
datefmtstr str

date format for log entries. Defaults to "%d.%m.%Y %H:%M:%S".

'%d.%m.%Y %H:%M:%S'
filename str

name of log file. Defaults to "".

''

Returns:

Type Description
Logger

logging.Logger: logger object

Source code in src/utils_mystuff/utils_various.py
def initLogger(
    loggername: str,
    formatstr: str = "%(asctime)s\t%(levelname)s\t%(message)s",
    datefmtstr: str = "%d.%m.%Y %H:%M:%S",
    filename: str = ""
) -> logging.Logger:
    """
    initLogger - initialize standard logger object

    Args:
        loggername (str): name of logger
        formatstr (str, optional): format string for log entries. Defaults to "%(asctime)s\t%(levelname)s\t%(message)s".
        datefmtstr (str, optional): date format for log entries. Defaults to "%d.%m.%Y %H:%M:%S".
        filename (str, optional): name of log file. Defaults to "".

    Returns:
        logging.Logger: logger object
    """

    global loggers

    if loggers.get(loggername):
        logger = loggers.get(loggername)
    else:
        logger = logging.getLogger(loggername)
        logformatter = logging.Formatter(formatstr, datefmt=datefmtstr)
        if filename == "":
            loghandler = logging.FileHandler(os.path.join(tempfile.gettempdir(), loggername + "_Py.txt"))
        else:
            loghandler = logging.FileHandler(filename)
        loghandler.setFormatter(logformatter)
        loghandler.setLevel(logging.INFO)
        logger.addHandler(loghandler)
        logger.setLevel(logging.INFO)
        loggers[loggername] = logger

    assert logger is not None
    return logger

init_logger(loggername: str, formatstr: str = '%(asctime)s\t%(levelname)s\t%(message)s', datefmtstr: str = '%d.%m.%Y %H:%M:%S', filename: str = '') -> logging.Logger

init_logger - initialize standard logger object

Parameters:

Name Type Description Default
loggername str

name of logger

required
formatstr str

format string for log entries. Defaults to "%(asctime)s %(levelname)s %(message)s".

'%(asctime)s\t%(levelname)s\t%(message)s'
datefmtstr str

date format for log entries. Defaults to "%d.%m.%Y %H:%M:%S".

'%d.%m.%Y %H:%M:%S'
filename str

name of log file. Defaults to "".

''

Returns:

Type Description
Logger

logging.Logger: logger object

Source code in src/utils_mystuff/utils_various.py
def init_logger(
    loggername: str,
    formatstr: str = "%(asctime)s\t%(levelname)s\t%(message)s",
    datefmtstr: str = "%d.%m.%Y %H:%M:%S",
    filename: str = ""
) -> logging.Logger:
    """
    init_logger - initialize standard logger object

    Args:
        loggername (str): name of logger
        formatstr (str, optional): format string for log entries. Defaults to "%(asctime)s\t%(levelname)s\t%(message)s".
        datefmtstr (str, optional): date format for log entries. Defaults to "%d.%m.%Y %H:%M:%S".
        filename (str, optional): name of log file. Defaults to "".

    Returns:
        logging.Logger: logger object
    """
    return initLogger(loggername, formatstr, datefmtstr, filename)

inputbox(text: str, title: str = '', default: str = '') -> Any

inputbox - caller stub for singleton GUIwrapperClass object method

Parameters:

Name Type Description Default
text str

prompt text

required
title str

title for popup. Defaults to empty string.

''
default str

default value. Defaults to empty string.

''

Returns:

Name Type Description
Any Any

entered value

Source code in src/utils_mystuff/utils_GUI.py
def inputbox(text: str, title: str = "", default: str = "") -> Any:
    """
    inputbox - caller stub for singleton GUIwrapperClass object method

    Args:
        text (str): prompt text
        title (str): title for popup. Defaults to empty string.
        default (str): default value. Defaults to empty string.

    Returns:
        Any: entered value
    """
    return GUIwrapper.inputbox(text, title, default)

is_date(checkvalue: Any, checkformat='%d.%m.%Y') -> bool

is_date - check if checkvalue is a date value

Parameters:

Name Type Description Default
checkvalue Any

value to be checked

required
checkformat str

dateformat for check of checkvalue of type str. Defaults to "%d.%m.%Y".

'%d.%m.%Y'

Returns:

Name Type Description
bool bool

checkvalue is date or not

Source code in src/utils_mystuff/utils_various.py
def is_date(checkvalue: Any, checkformat="%d.%m.%Y") -> bool:
    """
    is_date - check if checkvalue is a date value

    Args:
        checkvalue (Any): value to be checked
        checkformat (str, optional): dateformat for check of checkvalue of type str. Defaults to "%d.%m.%Y".

    Returns:
        bool: checkvalue is date or not
    """
    return isdate(checkvalue, checkformat)

is_file_locked(filepath: str, waittime: float = 0.1) -> bool

is_file_locked - check if file is locked

Parameters:

Name Type Description Default
filepath str

file to be checked

required
waittime float

waiting time for check. Defaults to 0.1.

0.1

Returns:

Name Type Description
bool bool

lock indicator

Source code in src/utils_mystuff/utils_filehandling.py
def is_file_locked(filepath: str, waittime: float = 0.1) -> bool:
    """
    is_file_locked - check if file is locked

    Args:
        filepath (str): file to be checked
        waittime (float, optional): waiting time for check. Defaults to 0.1.

    Returns:
        bool: lock indicator
    """
    return file_locked(filepath, waittime)

isdate(checkvalue: Any, checkformat='%d.%m.%Y') -> bool

isdate - check if checkvalue is a date value

Parameters:

Name Type Description Default
checkvalue Any

value to be checked

required
checkformat str

dateformat for check of checkvalue of type str. Defaults to "%d.%m.%Y".

'%d.%m.%Y'

Returns:

Name Type Description
bool bool

checkvalue is date or not

Source code in src/utils_mystuff/utils_various.py
def isdate(checkvalue: Any, checkformat="%d.%m.%Y") -> bool:
    """
    isdate - check if checkvalue is a date value

    Args:
        checkvalue (Any): value to be checked
        checkformat (str, optional): dateformat for check of checkvalue of type str. Defaults to "%d.%m.%Y".

    Returns:
        bool: checkvalue is date or not
    """

    if checkvalue is None or checkvalue == "":
        return False
    # elif type(checkvalue).__name__ == "datetime" or type(checkvalue).__name__ == "date":
    elif isinstance(checkvalue, (datetime.datetime, datetime.date)):
        return True
    elif isinstance(checkvalue, str):
        try:
            check = bool(datetime.datetime.strptime(checkvalue, checkformat))
        except ValueError:
            check = False
        return check
    else:
        return False

listbox(text: str, title: str = '', choices: list[str] = [], multiselect: bool = False) -> Union[str, list[str]]

listbox - caller stub for singleton GUIwrapperClass object method

Parameters:

Name Type Description Default
text str

prompt text

required
title str

title for popup. Defaults to empty string.

''
choices List[str]

Choices for listbox. Defaults to [].

[]
multiselect bool

Flag for multi-select mode. Defaults to False.

False

Returns:

Type Description
Union[str, list[str]]

Union[str, List[str]]: selected option(s)

Source code in src/utils_mystuff/utils_GUI.py
def listbox(
    text: str,
    title: str = "",
    choices: list[str] = [],
    multiselect: bool = False
) -> Union[str, list[str]]:
    """
    listbox - caller stub for singleton GUIwrapperClass object method

    Args:
        text (str): prompt text
        title (str): title for popup. Defaults to empty string.
        choices (List[str]): Choices for listbox. Defaults to [].
        multiselect (bool): Flag for multi-select mode. Defaults to False.

    Returns:
        Union[str, List[str]]: selected option(s)
    """
    return GUIwrapper.listbox(text, title, choices, multiselect)

load_textfile(txt_filename: str, mode: str = 'str') -> Union[list[str], str]

load_textfile - load textfile to list of strings or str

Parameters:

Name Type Description Default
txt_filename str

source text file

required
mode str

return mode - 'list', 'str' or 'strcleaned'. Defaults to 'str'.

'str'

Returns:

Type Description
Union[list[str], str]

Union[list[str], str]: content of textfile as list of string or string

Source code in src/utils_mystuff/utils_filehandling.py
def load_textfile(txt_filename: str, mode: str = "str") -> Union[list[str], str]:
    """
    load_textfile - load textfile to list of strings or str

    Args:
        txt_filename (str): source text file
        mode (str, optional): return mode - 'list', 'str' or 'strcleaned'. Defaults to 'str'.

    Returns:
        Union[list[str], str]: content of textfile as list of string or string
    """

    txt: Union[list[str], str] = ""

    fileexists = os.path.isfile(txt_filename)

    # read to list of lines
    if mode == "list":
        if fileexists:
            # via pathlib
            # txt = pathlib.Path(txt_filename).read_text()
            # via normal open file
            with open(txt_filename, "r") as txt_file:
                txt = txt_file.readlines()
            txt_file.close()
        else:
            txt = []
    # read to single string incl. CR
    elif mode == "str":
        if fileexists:
            with open(txt_filename, "r") as txt_file:
                txt = txt_file.read()
            txt_file.close()
        else:
            txt = ""
    # read to single string without CR
    elif mode == "strcleaned":
        if fileexists:
            with open(txt_filename, "r") as txt_file:
                txt = txt_file.read().replace("\n", "")
            txt_file.close()
        else:
            txt = ""
    else:
        err_msg = "Invalid mode."
        raise Exception(err_msg)

    return txt

logCLIargs() -> None

logCLIargs - write command line interface parameters to specific CLI call log

Source code in src/utils_mystuff/logger_CLI.py
def logCLIargs() -> None:
    """
    logCLIargs - write command line interface parameters to specific CLI call log
    """

    if sys.argv[0] != "-c":
        loggerCLI.info(f"Name Python script: {sys.argv[0]}")
    else:
        stack = inspect.stack()
        loggerCLI.info(
            f"Name Python script: {stack[len(inspect.stack()) - 2].filename} (retrieved from call stack because call using switch -c)"
        )
    argcount = len(sys.argv)
    if argcount > 1:
        for i in range(1, argcount):
            loggerCLI.info(f"Arg {i}: {sys.argv[i]}")
        loggerCLI.info(f"Number of args passed: {argcount - 1}")
    else:
        loggerCLI.info("No args passed.")
    # loggerCLI.info("\n")
    loggerCLI.newline()

logCLIparams(params) -> None

logCLIparams - write parsed parameters to specific call log

Parameters:

Name Type Description Default
params _type_

params

required
Source code in src/utils_mystuff/logger_CLI.py
def logCLIparams(params) -> None:
    """
    logCLIparams - write parsed parameters to specific call log

    Args:
        params (_type_): params
    """

    loggerCLI.info("Parsed arguments (from command line or via parameter injected into parse_args):")
    for param in vars(params):  # params is NamespaceObject of type TapType and not iterable
        if param in params.class_variables or param in params.argument_buffer:
            loggerCLI.info(f"{param}: {getattr(params, param)}")
    # loggerCLI.info("\n")
    loggerCLI.newline()

log_cli_args() -> None

log_cli_args - write command line interface parameters to specific CLI call log

Source code in src/utils_mystuff/logger_CLI.py
def log_cli_args() -> None:
    """
    log_cli_args - write command line interface parameters to specific CLI call log
    """
    logCLIargs()

log_cli_params(params) -> None

log_cli_params - write parsed parameters to specific call log

Parameters:

Name Type Description Default
params _type_

params

required
Source code in src/utils_mystuff/logger_CLI.py
def log_cli_params(params) -> None:
    """
    log_cli_params - write parsed parameters to specific call log

    Args:
        params (_type_): params
    """
    logCLIparams(params)

read_configfile(configfile: str, optionxform: Optional[Callable[[str], str]] = None, encoding: str = 'utf-8') -> configparser.ConfigParser

read_configfile - read config file with standardized boolean states into ConfigParser object

Parameters:

Name Type Description Default
configfile str

config file

required
optionxform callable[[str], str]]

callable to pass on to ConfigParser.optionxform. Defaults to None.

None
encoding str

file encoding. Defaults to "utf-8".

'utf-8'

Raises:

Type Description
Exception

file 'configfile' does not exist.

Returns:

Type Description
ConfigParser

configparser.ConfigParser: config parser object

Source code in src/utils_mystuff/utils_various.py
def read_configfile(
    configfile: str,
    optionxform: Optional[Callable[[str], str]] = None,
    encoding: str = "utf-8"
) -> configparser.ConfigParser:
    """
    read_configfile - read config file with standardized boolean states into ConfigParser object

    Args:
        configfile (str): config file
        optionxform (callable[[str], str]], optional): callable to pass on to ConfigParser.optionxform. Defaults to None.
        encoding (str, optional): file encoding. Defaults to "utf-8".

    Raises:
        Exception: file 'configfile' does not exist.

    Returns:
        configparser.ConfigParser: config parser object
    """
    return readconfigfile(configfile, optionxform, encoding)

readconfigfile(configfile: str, optionxform: Optional[Callable[[str], str]] = None, encoding: str = 'utf-8') -> configparser.ConfigParser

readconfigfile - read config file with standardized boolean states into ConfigParser object

Parameters:

Name Type Description Default
configfile str

config file

required
optionxform callable[[str], str]]

callable to pass on to ConfigParser.optionxform. Defaults to None.

None
encoding str

file encoding. Defaults to "utf-8".

'utf-8'

Raises:

Type Description
Exception

file 'configfile' does not exist.

Returns:

Type Description
ConfigParser

configparser.ConfigParser: config parser object

Source code in src/utils_mystuff/utils_various.py
def readconfigfile(
    configfile: str,
    optionxform: Optional[Callable[[str], str]] = None,
    encoding: str = "utf-8"
) -> configparser.ConfigParser:
    """
    readconfigfile - read config file with standardized boolean states into ConfigParser object

    Args:
        configfile (str): config file
        optionxform (callable[[str], str]], optional): callable to pass on to ConfigParser.optionxform. Defaults to None.
        encoding (str, optional): file encoding. Defaults to "utf-8".

    Raises:
        Exception: file 'configfile' does not exist.

    Returns:
        configparser.ConfigParser: config parser object
    """

    # no path provided as part of name of configfile, only filename -> use execution directory as default
    if configfile == os.path.basename(configfile):
        configfile = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), configfile)

    if not os.path.isfile(configfile):
        err_msg = f"Error reading ini file '{configfile}'. File does not exist"
        raise Exception(err_msg)

    config = configparser.ConfigParser(interpolation=configparser.ExtendedInterpolation())
    if optionxform is not None:
        config.optionxform = optionxform  # type: ignore
    config.BOOLEAN_STATES = {  # type: ignore
        "1": True, "True": True, "true": True, "Yes": True, "yes": True,
        "0": False, "False": False, "false": False, "No": False, "no": False
    }

    config.read(configfile, encoding=encoding)

    return config

setGUI(gui: str) -> None

setGUI - caller stub for singleton GUIwrapperClass object method to set GUI framework

currently supported GUI frameworks are 'easygui', 'pymsgbox', 'freesimplegui' (as FOSS predecessor of 'PySimpleGUI')

Parameters:

Name Type Description Default
gui str

GUI framework selector

required

Raises:

Type Description
Exception

Exception if invalid GUI framework selector provided.

Source code in src/utils_mystuff/utils_GUI.py
def setGUI(gui: str) -> None:
    """
    setGUI - caller stub for singleton GUIwrapperClass object method to set GUI framework

    currently supported GUI frameworks are 'easygui', 'pymsgbox', 'freesimplegui' (as FOSS predecessor of 'PySimpleGUI')

    Args:
        gui (str): GUI framework selector

    Raises:
        Exception: Exception if invalid GUI framework selector provided.
    """
    GUIwrapper.setGUI(gui)

setLogLevel(logger: logging.Logger, config: configparser.ConfigParser, section: str, optionLogLevel: str) -> None

setLogLevel - set log level from configparser object

Parameters:

Name Type Description Default
logger Logger

name of logger

required
config configparser

configparser object

required
section str

section in 'config'

required
optionLogLevel str

option in 'config'

required
Source code in src/utils_mystuff/utils_various.py
def setLogLevel(logger: logging.Logger, config: configparser.ConfigParser, section: str, optionLogLevel: str) -> None:
    """
    setLogLevel - set log level from configparser object

    Args:
        logger (logging.Logger): name of logger
        config (configparser): configparser object
        section (str): section in 'config'
        optionLogLevel (str): option in 'config'
    """

    if (logger is not None) and (config is not None):
        loglevelnum = getattr(logging, config[section][optionLogLevel].upper(), None)
        if isinstance(loglevelnum, int):
            logger.setLevel(loglevelnum)
        else:
            logger.setLevel(logging.INFO)

set_gui(gui: str) -> None

set_gui - caller stub for singleton GUIwrapperClass object method to set GUI framework

currently supported GUI frameworks are 'easygui', 'pymsgbox', 'freesimplegui' (as FOSS predecessor of 'PySimpleGUI')

Parameters:

Name Type Description Default
gui str

GUI framework selector

required

Raises:

Type Description
Exception

Exception if invalid GUI framework selector provided.

Source code in src/utils_mystuff/utils_GUI.py
def set_gui(gui: str) -> None:
    """
    set_gui - caller stub for singleton GUIwrapperClass object method to set GUI framework

    currently supported GUI frameworks are 'easygui', 'pymsgbox', 'freesimplegui' (as FOSS predecessor of 'PySimpleGUI')

    Args:
        gui (str): GUI framework selector

    Raises:
        Exception: Exception if invalid GUI framework selector provided.
    """
    GUIwrapper.setGUI(gui)

set_loglevel(logger: logging.Logger, config: configparser.ConfigParser, section: str, optionLogLevel: str) -> None

set_logLevel - set log level from cCallableonfigparser object

Parameters:

Name Type Description Default
logger Logger

name of logger

required
config configparser

configparser object

required
section str

section in 'config'

required
optionLogLevel str

option in 'config'

required
Source code in src/utils_mystuff/utils_various.py
def set_loglevel(logger: logging.Logger, config: configparser.ConfigParser, section: str, optionLogLevel: str) -> None:
    """
    set_logLevel - set log level from cCallableonfigparser object

    Args:
        logger (logging.Logger): name of logger
        config (configparser): configparser object
        section (str): section in 'config'
        optionLogLevel (str): option in 'config'
    """
    setLogLevel(logger, config, section, optionLogLevel)

set_loglevel_from_config(logger: logging.Logger, config: configparser.ConfigParser, section: str, optionLogLevel: str) -> None

set_loglevel_from_config - set log level from configparser object

Parameters:

Name Type Description Default
logger Logger

name of logger

required
config configparser

configparser object

required
section str

section in 'config'

required
optionLogLevel str

option in 'config'

required
Source code in src/utils_mystuff/utils_various.py
def set_loglevel_from_config(logger: logging.Logger, config: configparser.ConfigParser, section: str, optionLogLevel: str) -> None:
    """
    set_loglevel_from_config - set log level from configparser object

    Args:
        logger (logging.Logger): name of logger
        config (configparser): configparser object
        section (str): section in 'config'
        optionLogLevel (str): option in 'config'
    """
    setLogLevel(logger, config, section, optionLogLevel)

setlocale(locale_value: str)

setlocale - switch locale threadsafe

Parameters:

Name Type Description Default
locale_value str

target locale

required
Source code in src/utils_mystuff/utils_various.py
@contextmanager
def setlocale(locale_value: str):
    """
    setlocale - switch locale threadsafe

    Args:
        locale_value (str): target locale
    """

    with LOCALE_LOCK:
        saved_locale_value = locale.setlocale(locale.LC_ALL)
        try:
            yield locale.setlocale(locale.LC_ALL, locale_value)
        finally:
            locale.setlocale(locale.LC_ALL, saved_locale_value)

setup_CLI_logger(loggerNameCLIlog: str, *, switch_via_handler: bool = False) -> logging.Logger

setup_CLI_logger - encapsulated setup of CLI logger object

Parameters:

Name Type Description Default
loggerNameCLIlog str

name of logger.

required
switch_via_handler bool

define switching mode. Defaults to False.

False

Returns:

Name Type Description
Logger Logger

logger object

Source code in src/utils_mystuff/logger_CLI.py
def setup_CLI_logger(loggerNameCLIlog: str, *, switch_via_handler: bool = False) -> logging.Logger:
    """
    setup_CLI_logger - encapsulated setup of CLI logger object

    Args:
        loggerNameCLIlog (str): name of logger.
        switch_via_handler (bool): define switching mode. Defaults to False.

    Returns:
        Logger: logger object
    """

    # get logger
    loggerCLI = logging.getLogger(loggerNameCLIlog)

    # log file handler
    # log_filehandler = logging.FileHandler(os.path.join(tempfile.gettempdir(), loggerNameCLIlog + "_Py.txt"))

    # log formatter - normal & blank line
    formatter_standard = logging.Formatter("%(asctime)s\t%(levelname)s\t%(message)s", datefmt="%d.%m.%Y %H:%M:%S")
    formatter_blank = logging.Formatter(fmt="")

    if switch_via_handler:

        # log handler for normal log entries
        # handlerCLI = log_filehandler
        handlerCLI = logging.FileHandler(os.path.join(tempfile.gettempdir(), loggerNameCLIlog + "_Py.txt"))
        handlerCLI.setFormatter(formatter_standard)
        handlerCLI.setLevel(logging.INFO)

        # log handler for blank lines
        # loghandlerNewline = log_filehandler
        handlerNewline = logging.FileHandler(os.path.join(tempfile.gettempdir(), loggerNameCLIlog + "_Py.txt"))
        handlerNewline.setFormatter(formatter_blank)
        handlerNewline.setLevel(logging.INFO)

        # set handler for log object
        loggerCLI.addHandler(handlerCLI)
        loggerCLI.setLevel(logging.INFO)

        # set own switching attributes
        loggerCLI.handler_standard = handlerCLI
        loggerCLI.handler_newline = handlerNewline
        loggerCLI.newline = types.MethodType(_logger_newline_switch_handler, loggerCLI)

    else:

        handler = logging.FileHandler(os.path.join(tempfile.gettempdir(), loggerNameCLIlog + "_Py.txt"))
        handler.setFormatter(formatter_standard)
        handler.setLevel(logging.INFO)

        # set handler for log object
        loggerCLI.addHandler(handler)
        loggerCLI.setLevel(logging.INFO)

        # set own switching attributes
        loggerCLI.handler = handler
        loggerCLI.formatter_standard = formatter_standard
        loggerCLI.formatter_blank = formatter_blank
        loggerCLI.newline = types.MethodType(_logger_newline_switch_formatter, loggerCLI)

    return loggerCLI

to_bool(value: Union[str, int, float, bool], truevalues: list[str] = ['true', 'yes', 'x', '1', '-1']) -> bool

to_bool - convert basic scalar types to bool

Parameters:

Name Type Description Default
value Union[str, int, float, bool]

value to be checked

required
truevalues list[str]

truthy str values. Defaults to ["true", "yes", "x", "1", "-1"].

['true', 'yes', 'x', '1', '-1']

Returns:

Name Type Description
bool bool

truthiness of value

Source code in src/utils_mystuff/utils_various.py
def to_bool(value: Union[str, int, float, bool], truevalues: list[str] = ["true", "yes", "x", "1", "-1"]) -> bool:
    """
    to_bool - convert basic scalar types to  bool

    Args:
        value (Union[str, int, float, bool]): value to be checked
        truevalues (list[str], optional): truthy str values. Defaults to ["true", "yes", "x", "1", "-1"].


    Returns:
        bool: truthiness of value
    """

    if type(value) is bool:
        return value
    elif type(value) in {int, float}:
        return value != 0
    elif type(value) is str:
        return value.lower() in truevalues
    else:
        return False

to_boolean(value: Union[str, int, float, bool], truevalues: list[str] = ['true', 'yes', 'x', '1', '-1']) -> bool

to_boolean - convert basic scalar types to bool

Parameters:

Name Type Description Default
value Union[str, int, float, bool]

value to be checked

required
truevalues list[str]

truthy str values. Defaults to ["true", "yes", "x", "1", "-1"].

['true', 'yes', 'x', '1', '-1']

Returns:

Name Type Description
bool bool

truthiness of value

Source code in src/utils_mystuff/utils_various.py
def to_boolean(value: Union[str, int, float, bool], truevalues: list[str] = ["true", "yes", "x", "1", "-1"]) -> bool:
    """
    to_boolean - convert basic scalar types to  bool

    Args:
        value (Union[str, int, float, bool]): value to be checked
        truevalues (list[str], optional): truthy str values. Defaults to ["true", "yes", "x", "1", "-1"].

    Returns:
        bool: truthiness of value
    """

    return to_bool(value, truevalues)