Module gdess.formatters.args
Expand source code
import argparse, logging, os, shlex, tempfile
from typing import Union
_logger = logging.getLogger(__name__)
def options_to_args(options: dict) -> list:
"""Convert a dictionary to a list of strings so that an ArgumentParser can parse it.
Parameters
----------
options : dict
Examples
--------
a = {'start_yr': "1980", 'end_yr': "2010"}
>>> options_to_args(a)
returns ['--start_yr', '1980', '--end_yr', '2010']
Returns
-------
list
"""
return shlex.split(' '.join([f"--{k} {v}" for k, v in options.items()]))
def is_some_none(val) -> bool:
"""Check if value is either a Python None object or the case-insensitive string 'None'
"""
if val is None:
return True
elif isinstance(val, str) and (val.lower() == 'none'):
return True
else:
return False
def nullable_int(val: Union[None, int]) -> Union[None, int]:
"""Validate whether a value's type is either an integer or none
Parameters
----------
val
value to validate
Raises
------
argparse.ArgumentTypeError
if the value is not either an integer or None
Returns
-------
int or None
"""
if is_some_none(val):
return None
if not isinstance(val, int):
raise argparse.ArgumentTypeError("Value must be an integer, None, or 'None'.")
return val
def nullable_str(val: Union[None, str]) -> Union[None, str]:
"""Validate whether a value's type is either a string or none
Parameters
----------
val
value to validate
Raises
------
argparse.ArgumentTypeError
if the value is not either a string or None
Returns
-------
str or None
"""
if is_some_none(val):
return None
if not isinstance(val, str):
raise argparse.ArgumentTypeError('Value must be an string or None.')
return val
def valid_year_string(y: Union[str, int]) -> Union[None, str]:
"""Validate 'year' argument passed in as a recipe option
Parameters
----------
y
year to validate
Raises
------
argparse.ArgumentTypeError
if the year is not a valid string or positive integer less than 10,000
Returns
-------
str or None
"""
if is_some_none(y):
return None
elif isinstance(y, str) | isinstance(y, int):
if 0 <= int(y) <= 10000:
return str(y)
raise argparse.ArgumentTypeError('Year must be a string or integer whose value is between 0 and 10,000.')
def valid_existing_path(p: Union[str, os.PathLike]
) -> Union[str, os.PathLike]:
"""Validate a filepath argument passed in as a recipe option
Parameters
----------
p
path to validate
Raises
------
argparse.ArgumentTypeError
if the input path does not exist and/or is not writable
Returns
-------
str or os.PathLike
"""
try:
if os.path.exists(p):
if os.access(p, os.R_OK):
return p
except TypeError:
pass
raise argparse.ArgumentTypeError('Path must exist and be readable. <%s> is not.' % p)
def valid_writable_path(p: Union[str, os.PathLike]
) -> Union[bool, str, os.PathLike]:
"""Validate a filepath argument passed in as a recipe option
Parameters
----------
p
path to validate
Raises
------
argparse.ArgumentTypeError
if the input path is not valid and writable
Returns
-------
bool, str, or os.PathLike
"""
def canmakeit():
try:
os.makedirs(os.path.dirname(p), exist_ok=True)
with tempfile.NamedTemporaryFile(prefix='_temp', dir=os.path.dirname(p)) as file_object:
_logger.debug("Testing - successfully created temporary file (%s)." % file_object.name)
except:
raise argparse.ArgumentTypeError('Path must be valid and writable. <%s> is not.' % p)
return True
if (p is None) or (not canmakeit()):
raise argparse.ArgumentTypeError('Path must be valid and writable. <%s> is not.' % p)
return p
Functions
def is_some_none(val) -> bool-
Check if value is either a Python None object or the case-insensitive string 'None'
Expand source code
def is_some_none(val) -> bool: """Check if value is either a Python None object or the case-insensitive string 'None' """ if val is None: return True elif isinstance(val, str) and (val.lower() == 'none'): return True else: return False def nullable_int(val: Union[NoneType, int]) -> Union[NoneType, int]-
Validate whether a value's type is either an integer or none
Parameters
val- value to validate
Raises
argparse.ArgumentTypeError- if the value is not either an integer or None
Returns
intorNone
Expand source code
def nullable_int(val: Union[None, int]) -> Union[None, int]: """Validate whether a value's type is either an integer or none Parameters ---------- val value to validate Raises ------ argparse.ArgumentTypeError if the value is not either an integer or None Returns ------- int or None """ if is_some_none(val): return None if not isinstance(val, int): raise argparse.ArgumentTypeError("Value must be an integer, None, or 'None'.") return val def nullable_str(val: Union[NoneType, str]) -> Union[NoneType, str]-
Validate whether a value's type is either a string or none
Parameters
val- value to validate
Raises
argparse.ArgumentTypeError- if the value is not either a string or None
Returns
strorNone
Expand source code
def nullable_str(val: Union[None, str]) -> Union[None, str]: """Validate whether a value's type is either a string or none Parameters ---------- val value to validate Raises ------ argparse.ArgumentTypeError if the value is not either a string or None Returns ------- str or None """ if is_some_none(val): return None if not isinstance(val, str): raise argparse.ArgumentTypeError('Value must be an string or None.') return val def options_to_args(options: dict) -> list-
Convert a dictionary to a list of strings so that an ArgumentParser can parse it.
Parameters
options:dict
Examples
a = {'start_yr': "1980", 'end_yr': "2010"}
>>> options_to_args(a) returns ['--start_yr', '1980', '--end_yr', '2010']Returns
list
Expand source code
def options_to_args(options: dict) -> list: """Convert a dictionary to a list of strings so that an ArgumentParser can parse it. Parameters ---------- options : dict Examples -------- a = {'start_yr': "1980", 'end_yr': "2010"} >>> options_to_args(a) returns ['--start_yr', '1980', '--end_yr', '2010'] Returns ------- list """ return shlex.split(' '.join([f"--{k} {v}" for k, v in options.items()])) def valid_existing_path(p: Union[str, os.PathLike]) -> Union[str, os.PathLike]-
Validate a filepath argument passed in as a recipe option
Parameters
p- path to validate
Raises
argparse.ArgumentTypeError- if the input path does not exist and/or is not writable
Returns
stroros.PathLike
Expand source code
def valid_existing_path(p: Union[str, os.PathLike] ) -> Union[str, os.PathLike]: """Validate a filepath argument passed in as a recipe option Parameters ---------- p path to validate Raises ------ argparse.ArgumentTypeError if the input path does not exist and/or is not writable Returns ------- str or os.PathLike """ try: if os.path.exists(p): if os.access(p, os.R_OK): return p except TypeError: pass raise argparse.ArgumentTypeError('Path must exist and be readable. <%s> is not.' % p) def valid_writable_path(p: Union[str, os.PathLike]) -> Union[bool, str, os.PathLike]-
Validate a filepath argument passed in as a recipe option
Parameters
p- path to validate
Raises
argparse.ArgumentTypeError- if the input path is not valid and writable
Returns
bool, str,oros.PathLike
Expand source code
def valid_writable_path(p: Union[str, os.PathLike] ) -> Union[bool, str, os.PathLike]: """Validate a filepath argument passed in as a recipe option Parameters ---------- p path to validate Raises ------ argparse.ArgumentTypeError if the input path is not valid and writable Returns ------- bool, str, or os.PathLike """ def canmakeit(): try: os.makedirs(os.path.dirname(p), exist_ok=True) with tempfile.NamedTemporaryFile(prefix='_temp', dir=os.path.dirname(p)) as file_object: _logger.debug("Testing - successfully created temporary file (%s)." % file_object.name) except: raise argparse.ArgumentTypeError('Path must be valid and writable. <%s> is not.' % p) return True if (p is None) or (not canmakeit()): raise argparse.ArgumentTypeError('Path must be valid and writable. <%s> is not.' % p) return p def valid_year_string(y: Union[str, int]) -> Union[NoneType, str]-
Validate 'year' argument passed in as a recipe option
Parameters
y- year to validate
Raises
argparse.ArgumentTypeError- if the year is not a valid string or positive integer less than 10,000
Returns
strorNone
Expand source code
def valid_year_string(y: Union[str, int]) -> Union[None, str]: """Validate 'year' argument passed in as a recipe option Parameters ---------- y year to validate Raises ------ argparse.ArgumentTypeError if the year is not a valid string or positive integer less than 10,000 Returns ------- str or None """ if is_some_none(y): return None elif isinstance(y, str) | isinstance(y, int): if 0 <= int(y) <= 10000: return str(y) raise argparse.ArgumentTypeError('Year must be a string or integer whose value is between 0 and 10,000.')