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)
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. | '' |
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
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
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. | '' |
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. | '' |
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
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_params(params) -> None ¶
log_cli_params - write parsed parameters to specific call log
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params | _type_ | params | required |
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)