'''
General utility functions for the clinvar-build module
'''
import os
from typing import (
Any,
Callable,
Optional,
)
from clinvar_build.errors import (
is_type,
)
from clinvar_build.errors import (
is_type,
)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[docs]
def assign_empty_default(arguments:list[Any], empty_object:Callable[[],Any],
) -> list[Any]:
'''
Takes a list of `arguments`, checks if these are `NoneType` and if so
asigns them 'empty_object'.
Parameters
----------
arguments: `list` [`any`]
A list of arguments which may be set to `NoneType`.
empty_object: `Callable`
A function that returns a mutable object
Examples include a `list` or a `dict`.
Returns
-------
new_arguments: list
List with `NoneType` replaced by empty mutable object.
Examples
--------
>>> assign_empty_default(['hi', None, 'hello'], empty_object=list)
['hi', [], 'hello']
Notes
-----
This function helps deal with the pitfall of assigning an empty mutable
object as a default function argument, which would persist through multiple
function calls, leading to unexpected/undesired behaviours.
'''
# check input
is_type(arguments, list)
is_type(empty_object, type)
# loop over arguments
new_args = [empty_object() if arg is None else arg for arg in arguments]
# return
return new_args
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def _update_kwargs(update_dict:dict[Any, Any], **kwargs:Optional[Any],
) -> dict[Any, Any]:
'''
This function will take any number of `kwargs` and add them to an
`update_dict`. If there are any duplicate values in the `kwargs` and the
`update_dict`, the entries in the `update_dict` will take precedence.
Parameters
----------
update_dict : `dict`
A dictionary with key - value pairs that should be combined with any
of the supplied kwargs.
kwargs : `Any`
Arbitrary keyword arguments.
Returns
-------
dict:
A dictionary with the update_dict and kwargs combined, where duplicate
entries from update_dict overwrite those in kwargs.
Examples
--------
The function is particularly useful to overwrite `kwargs` that are
supplied to a nested function say
>>> _update_kwargs(update_dict={'c': 'black'}, c='red',
alpha = 0.5)
>>> {'c': 'black', 'alpha': 0.5}
'''
new_dict = {**kwargs, **update_dict}
# returns
return new_dict
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def _check_directory(root):
"""
Does directory exist.
"""
if os.path.isdir(root) == False:
raise IOError('Directory {} does not exist'.format(root))
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def _check_directory_readable(root):
"""
Do we have read access. Note this should work on a directory or file.
"""
if os.access(root, os.R_OK) == False:
raise PermissionError(
'You do not have read-access to: `{}`'.format(root)
)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def _check_directory_writable(root):
"""
Check if we have write access to a directory or file.
"""
if os.access(root, os.W_OK) == False:
raise PermissionError(
f'You do not have write-access to: `{root}`'
)