Module ARgorithmToolkit.parser
Parser module deals with parsing .config.json files.
Expand source code
# pylint: skip-file
"""Parser module deals with parsing .config.json files."""
import os
import json
import re
import math
import inspect
import typer
from jsonschema import Draft7Validator
from jsonschema.exceptions import ValidationError
import ARgorithmToolkit
with open(os.path.join(ARgorithmToolkit.__path__[0],'data/config.schema.json')) as schema:
CONFIG_SCHEMA = json.load(schema)
config_cli_heading ="""
+-----------------------------+
| |
| ARGORITHM CONFIG GENERATOR |
| |
+-----------------------------+
"""
PRIORITY = {
"INT" : 0,
"STRING" : 2,
"FLOAT" : 1,
"ARRAY" : 3,
"MATRIX" : 4
}
def multiline():
"""takes multiline input."""
buffer = ''
while True:
try:
line = input()
except EOFError:
break
if not line:
break
buffer += line+"\n"
return buffer[:-1]
def master_heading():
"""Renders the ARgorithm config generator heading."""
text = typer.style(config_cli_heading,fg=typer.colors.WHITE,bold=True)
typer.echo(text)
def heading(title,message):
"""Create a heading text.
Args:
title (str): The title of the heading
message (str): The message that
"""
# typer.clear()
text = typer.style(title.upper(),fg=typer.colors.WHITE,bold=True)
typer.echo('-'*(len(text)+2))
typer.echo(text)
typer.echo('-'*(len(text)+2))
typer.echo(message+"\n")
return typer
def input_prompt(message,default=None,type=str,show_default=True):
"""Uses typer to create a single input field in CLI.
Args:
message (str): The input field text
type (type, optional): The type of input
default (type, optional): The default value if user does not enter any value
show_default (bool, optional): By default, True. If True shows the default value to user
Returns:
ip : The data entered by user
"""
text = typer.style(message,fg=typer.colors.WHITE)
if default:
ip = typer.prompt(text,default=default,type=type,show_default=show_default)
else:
ip = typer.prompt(text,type=type)
return ip
def confirm_prompt(message):
"""Uses typer to create a confirmation prompt.
Args:
message (str): The text for confirmation
Returns:
flag: boolean value as entered by user
"""
text = typer.style(message,fg=typer.colors.WHITE)
flag = typer.confirm(text)
return flag
def multiline_input_prompt(message):
"""Uses typer and ARgorithmToolkit.parser.multiline to create a multiline
input prompt.
Args:
message (str): The text for prompt
Returns:
ip: data entered by user
"""
text = typer.style(message + ':',fg=typer.colors.WHITE)
helptext = typer.style("Press ENTER on empty line to leave multiline input",fg=typer.colors.CYAN)
typer.echo(text)
typer.echo(helptext)
ip = multiline()
return ip
def info(message,data):
"""Display information using typer.
Args:
message (str): Description of the information
data : The data to be displayed
"""
message = typer.style(message,fg=typer.colors.WHITE)
data = typer.style(str(data),fg=typer.colors.GREEN)
typer.echo(message+": "+data)
def warning(message):
"""Generate warning message using typer.
Args:
message (str): warning text
"""
text = typer.style("⚠ " + message , fg=typer.colors.YELLOW)
typer.echo(text)
def find_parameters(filename,function):
"""Finds the keyword arguments accessed in the file.
find_parameters parses the code line by line and check which all keywords
were accessed in the function code within the code file
Args:
filename (str): filename of the codefile
function (str): function name where we need to check the kwargs
Returns:
params: list of keywords which need to be defined in config file
"""
function_regex = re.compile(f"^def.([A-Za-z0-9]+).?\(\*\*kwargs\)")
kwarg_regex = r"kwargs\[[\'\"]([A-Za-z0-9]+)[\'\"]\]"
with open(filename,'r') as codefile:
parameters = dict()
flag = False
line_count = -1
for line in codefile.readlines():
line_count += 1
search = re.search(function_regex,line)
if search:
func = list(search.groups())[0]
flag = func == function
if flag:
search = re.search(kwarg_regex,line)
if search:
params = list(search.groups())
for p in params:
if p not in parameters:
parameters[p] = line_count
param_list = sorted(
list(parameters.keys()) ,
key=lambda x: parameters[x]
)
return list(parameters)
def validateconfig(filepath):
"""Validates and stores argorithm config."""
validator = Draft7Validator(CONFIG_SCHEMA)
if os.path.isfile(filepath):
with open(filepath,'r') as configfile:
data = json.load(configfile)
try:
validator.validate(data)
except ValidationError as ve:
warning("Invalid config")
errors = sorted(validator.iter_errors(data), key=lambda e: e.path)
for e in errors:
print(e.message)
raise ve
return data
else:
raise FileNotFoundError("No config file")
def numeric_input(param,input_type):
"""Initiates numeric input from user for `INT` and `FLOAT` types.
Args:
param (dict): The parameter details
input_type ([type]): The type of numerical value
Returns:
value: value of type `input_type`
"""
retry = True
while retry:
retry = False
value = input_prompt("Enter integer value",type=input_type)
if "start" in param:
if value < param["start"]:
warning(f"Please enter value larger than {param['start']}")
retry = True
if "end" in param:
if value > param["end"]:
warning(f"Please enter value less than {param['end']}")
retry = True
return input_type(value)
def check_size(value,param,example):
"""Checks size of input with respect to parameter constraints.
Args:
value (list or str): The value entered by user
param (dict): The parameter details
example (dict): The output dictionary in which parameter values are stored
Returns:
example: returns updated output dictionary
"""
if "size" in param:
if isinstance(param["size"],str):
assert isinstance(example[param["size"]],int)
if len(value) != example[param["size"]]:
warning(f"length of input should be {example[param['size']]}")
return True
else:
if len(value) != param["size"]:
warning(f"length of input should be {param['size']}")
return True
return False
def input_data(parameters):
"""Generates a input form based on the parameters in config.
Args:
parameters (dict): The config parameters which will be used to generate the input fields
Returns:
example: The values for each param (key in parameters)
"""
example = {}
types = {
"INT" : int,
"FLOAT" : float,
"STRING" : str,
}
param_list = sorted(
list(parameters.keys()) ,
key=lambda x: PRIORITY[parameters[x]['type']]
)
heading("Enter input for ARgorithm","Based on argorithm parameters, input will be taken")
for key in param_list:
param = parameters[key]
# typer.clear()
info("\ninput keyword",key)
info("Description",param['description'])
if param["type"] == "INT":
value = numeric_input(param,int)
elif param["type"] == "FLOAT":
value = numeric_input(param,float)
elif param["type"] == "STRING":
retry = True
while retry:
retry = False
value = input_prompt("Enter string value" , type=str)
retry = check_size(value,param,example)
elif param["type"] == "ARRAY":
retry = True
while retry:
retry = False
value = input_prompt("Enter space separated series" , type=str).split(' ')
try:
value = [types[param['item-type']](x) for x in value]
except:
warning(f"elements must be of type {types[param['item-type']]}")
retry = True
retry = retry or check_size(value,param,example)
elif param["type"] == "MATRIX":
retry = True
while retry:
retry = False
if isinstance(param['row'],str):
row_count = example[param['row']]
else:
row_count = param['row']
if isinstance(param['col'],str):
col_count = example[param['col']]
else:
col_count = param['col']
typer.echo("Enter matrix input, elements in each row must be space separated")
info(f"no. of rows", row_count)
info(f"no. of elements per row",col_count)
value = []
for _ in range(row_count):
row_value = input_prompt("",type=str).split(' ')
if len(row_value) != col_count:
warning(f"row must have {col_count} space separated values")
retry = True
try:
row_value = [types[param['item-type']](x) for x in row_value]
except:
warning(f"elements must be of type {types[param['item-type']]}")
retry = True
if retry:
break
value.append(row_value)
example[key] = value
return example
def range_input(config,parameter_name):
"""Update config with the range for `INT` and `FLOAT` parameters.
Args:
config (dict): The config object where the parameter data has to be updated
parameter_name (str): The parameter whose metadata is being collected
"""
range_confirm = confirm_prompt(f"Do you want to add range constraints to {parameter_name}")
if range_confirm:
start = input_prompt("Enter lower limit",type=int,default=-math.inf,show_default=False)
if start != -math.inf:
config["parameters"][parameter_name]["start"] = start
end = input_prompt("Enter upper limit",type=int,default=math.inf,show_default=False)
if end != math.inf:
config["parameters"][parameter_name]["end"] = end
return config
def size_ref(config,parameter_name,data_field):
"""Inputs size constraint for `STRING`,`ARRAY` and `MATRIX` parameters.
Args:
data_field (str): What is the size constraint being used as
Returns:
size: Returns size constraint
"""
size = input_prompt(f"Enter integer value or name of INT type parameter for {data_field}")
try:
size = int(size)
except ValueError:
if size not in config["parameters"]:
info("creating INT parameter" , size)
config["parameters"][size] = {
"description" : f"defines {data_field} of {parameter_name} ({config['parameters'][parameter_name]['type']})",
"type" : "INT"
}
config = range_input(config,size)
config["parameters"][parameter_name][data_field] = size
return config
def define_parameter(config,parameter_name):
"""Nested function that asks use information regarding parameter.
Args:
config (dict): The config object where the parameter data has to be updated
parameter_name (str): The parameter whose metadata is being collected
Returns:
config: Returns updated config object
"""
parameter_types = ["INT","FLOAT","STRING","ARRAY","MATRIX"]
parameter_type = input_prompt("Enter parameter type")
while parameter_type not in parameter_types:
warning("Invalid parameter type. Accepted values: INT FLOAT ARRAY MATRIX STRING")
parameter_type = input_prompt("Enter parameter type")
config["parameters"][parameter_name]["type"] = parameter_type
if parameter_type == "INT":
config = range_input(config,parameter_name)
elif parameter_type == "FLOAT":
config = range_input(config,parameter_name)
elif parameter_type == "STRING":
range_confirm = confirm_prompt(f"Do you want to add range constraints to {parameter_name}")
if range_confirm:
config = size_ref(config,parameter_name,"size")
elif parameter_type == "ARRAY":
item_types = ["INT","FLOAT","STRING"]
item_type = input_prompt("Enter type of array element")
while item_type not in item_types:
warning("Invalid element type. Accepted values: INT FLOAT STRING")
item_type = input_prompt("Enter item type")
config["parameters"][parameter_name]["item-type"] = item_type
range_confirm = confirm_prompt(f"Do you want to add range constraints to {parameter_name}")
if range_confirm:
config = size_ref(config,parameter_name,"size")
elif parameter_type == "MATRIX":
item_types = ["INT","FLOAT","STRING"]
item_type = input_prompt("Enter type of array element")
while item_type not in item_types:
warning("Invalid element type. Accepted values: INT FLOAT STRING")
item_type = input_prompt("Enter item type")
config["parameters"][parameter_name]["item-type"] = item_type
config = size_ref(config,parameter_name,"row")
config = size_ref(config,parameter_name,"col")
parameter_description = multiline_input_prompt("Enter parameter description")
config["parameters"][parameter_name]["description"] = parameter_description
return config
def create(filepath):
"""implements the CLI config generator to run create config files using
CLI."""
master_heading()
config = {}
directory,filename = os.path.split(filepath)
info("ARgorithmID", filename.split(".")[0])
config["argorithmID"] = filename.split(".")[0]
config["file"] = config["argorithmID"]+".py"
function_regex = re.compile("def.([A-Za-z]+).?\(\*\*kwargs\)")
with open(os.path.join(directory,config['file']),"r") as codefile:
text = codefile.read()
func_list = list(re.search(function_regex,text).groups())
if len(func_list) == 0:
raise KeyError("No valid function in ARgorithm code")
info("Codefile found",config['file'])
function = input_prompt("which function should be called",default=func_list[0])
while function not in func_list:
warning("function not found in code")
function = input_prompt("enter valid function name",default=func_list[0])
config["function"] = function
config["description"] = multiline_input_prompt('Enter ARgorithm Description')
config["parameters"] = {}
typer.echo("Setting up parameters for your argorithm")
typer.echo("input keywords are used to map the input passed to your function as kwargs")
existing_parameters = find_parameters(os.path.join(directory,config['file']),config['function'])
if len(existing_parameters) > 0:
text = typer.style('The following input keywords were found in code')
typer.echo(text)
for param in existing_parameters:
typer.echo(typer.style("- "+param,fg=typer.colors.GREEN))
for param in existing_parameters:
if param in config['parameters']:
continue
info("input keyword",param)
config["parameters"][param] = {}
config = define_parameter(config,param)
confirm = confirm_prompt("Do you want to another input keyword")
while(confirm):
typer.echo("add details for parameter")
parameter_name = input_prompt("Enter parameter name")
name_regex = r"^[A-Za-z].*$"
while re.match(name_regex,parameter_name) is None:
warning("Invalid name")
parameter_name = input_prompt("re-enter parameter name")
config["parameters"][parameter_name] = {}
config = define_parameter(config,parameter_name)
confirm = confirm_prompt("Do you want to add parameter?")
example = input_data(config["parameters"])
config["example"] = example
with open(os.path.join(os.getcwd(),directory , filename) , 'w') as configfile:
json.dump(config,configfile,indent=4)
Functions
def check_size(value, param, example)
-
Checks size of input with respect to parameter constraints.
Args
value
:list
orstr
- The value entered by user
param
:dict
- The parameter details
example
:dict
- The output dictionary in which parameter values are stored
Returns
example
- returns updated output dictionary
Expand source code
def check_size(value,param,example): """Checks size of input with respect to parameter constraints. Args: value (list or str): The value entered by user param (dict): The parameter details example (dict): The output dictionary in which parameter values are stored Returns: example: returns updated output dictionary """ if "size" in param: if isinstance(param["size"],str): assert isinstance(example[param["size"]],int) if len(value) != example[param["size"]]: warning(f"length of input should be {example[param['size']]}") return True else: if len(value) != param["size"]: warning(f"length of input should be {param['size']}") return True return False
def confirm_prompt(message)
-
Uses typer to create a confirmation prompt.
Args
message
:str
- The text for confirmation
Returns
flag
- boolean value as entered by user
Expand source code
def confirm_prompt(message): """Uses typer to create a confirmation prompt. Args: message (str): The text for confirmation Returns: flag: boolean value as entered by user """ text = typer.style(message,fg=typer.colors.WHITE) flag = typer.confirm(text) return flag
def create(filepath)
-
implements the CLI config generator to run create config files using CLI.
Expand source code
def create(filepath): """implements the CLI config generator to run create config files using CLI.""" master_heading() config = {} directory,filename = os.path.split(filepath) info("ARgorithmID", filename.split(".")[0]) config["argorithmID"] = filename.split(".")[0] config["file"] = config["argorithmID"]+".py" function_regex = re.compile("def.([A-Za-z]+).?\(\*\*kwargs\)") with open(os.path.join(directory,config['file']),"r") as codefile: text = codefile.read() func_list = list(re.search(function_regex,text).groups()) if len(func_list) == 0: raise KeyError("No valid function in ARgorithm code") info("Codefile found",config['file']) function = input_prompt("which function should be called",default=func_list[0]) while function not in func_list: warning("function not found in code") function = input_prompt("enter valid function name",default=func_list[0]) config["function"] = function config["description"] = multiline_input_prompt('Enter ARgorithm Description') config["parameters"] = {} typer.echo("Setting up parameters for your argorithm") typer.echo("input keywords are used to map the input passed to your function as kwargs") existing_parameters = find_parameters(os.path.join(directory,config['file']),config['function']) if len(existing_parameters) > 0: text = typer.style('The following input keywords were found in code') typer.echo(text) for param in existing_parameters: typer.echo(typer.style("- "+param,fg=typer.colors.GREEN)) for param in existing_parameters: if param in config['parameters']: continue info("input keyword",param) config["parameters"][param] = {} config = define_parameter(config,param) confirm = confirm_prompt("Do you want to another input keyword") while(confirm): typer.echo("add details for parameter") parameter_name = input_prompt("Enter parameter name") name_regex = r"^[A-Za-z].*$" while re.match(name_regex,parameter_name) is None: warning("Invalid name") parameter_name = input_prompt("re-enter parameter name") config["parameters"][parameter_name] = {} config = define_parameter(config,parameter_name) confirm = confirm_prompt("Do you want to add parameter?") example = input_data(config["parameters"]) config["example"] = example with open(os.path.join(os.getcwd(),directory , filename) , 'w') as configfile: json.dump(config,configfile,indent=4)
def define_parameter(config, parameter_name)
-
Nested function that asks use information regarding parameter.
Args
config
:dict
- The config object where the parameter data has to be updated
parameter_name
:str
- The parameter whose metadata is being collected
Returns
config
- Returns updated config object
Expand source code
def define_parameter(config,parameter_name): """Nested function that asks use information regarding parameter. Args: config (dict): The config object where the parameter data has to be updated parameter_name (str): The parameter whose metadata is being collected Returns: config: Returns updated config object """ parameter_types = ["INT","FLOAT","STRING","ARRAY","MATRIX"] parameter_type = input_prompt("Enter parameter type") while parameter_type not in parameter_types: warning("Invalid parameter type. Accepted values: INT FLOAT ARRAY MATRIX STRING") parameter_type = input_prompt("Enter parameter type") config["parameters"][parameter_name]["type"] = parameter_type if parameter_type == "INT": config = range_input(config,parameter_name) elif parameter_type == "FLOAT": config = range_input(config,parameter_name) elif parameter_type == "STRING": range_confirm = confirm_prompt(f"Do you want to add range constraints to {parameter_name}") if range_confirm: config = size_ref(config,parameter_name,"size") elif parameter_type == "ARRAY": item_types = ["INT","FLOAT","STRING"] item_type = input_prompt("Enter type of array element") while item_type not in item_types: warning("Invalid element type. Accepted values: INT FLOAT STRING") item_type = input_prompt("Enter item type") config["parameters"][parameter_name]["item-type"] = item_type range_confirm = confirm_prompt(f"Do you want to add range constraints to {parameter_name}") if range_confirm: config = size_ref(config,parameter_name,"size") elif parameter_type == "MATRIX": item_types = ["INT","FLOAT","STRING"] item_type = input_prompt("Enter type of array element") while item_type not in item_types: warning("Invalid element type. Accepted values: INT FLOAT STRING") item_type = input_prompt("Enter item type") config["parameters"][parameter_name]["item-type"] = item_type config = size_ref(config,parameter_name,"row") config = size_ref(config,parameter_name,"col") parameter_description = multiline_input_prompt("Enter parameter description") config["parameters"][parameter_name]["description"] = parameter_description return config
def find_parameters(filename, function)
-
Finds the keyword arguments accessed in the file.
find_parameters parses the code line by line and check which all keywords were accessed in the function code within the code file
Args
filename
:str
- filename of the codefile
function
:str
- function name where we need to check the kwargs
Returns
params
- list of keywords which need to be defined in config file
Expand source code
def find_parameters(filename,function): """Finds the keyword arguments accessed in the file. find_parameters parses the code line by line and check which all keywords were accessed in the function code within the code file Args: filename (str): filename of the codefile function (str): function name where we need to check the kwargs Returns: params: list of keywords which need to be defined in config file """ function_regex = re.compile(f"^def.([A-Za-z0-9]+).?\(\*\*kwargs\)") kwarg_regex = r"kwargs\[[\'\"]([A-Za-z0-9]+)[\'\"]\]" with open(filename,'r') as codefile: parameters = dict() flag = False line_count = -1 for line in codefile.readlines(): line_count += 1 search = re.search(function_regex,line) if search: func = list(search.groups())[0] flag = func == function if flag: search = re.search(kwarg_regex,line) if search: params = list(search.groups()) for p in params: if p not in parameters: parameters[p] = line_count param_list = sorted( list(parameters.keys()) , key=lambda x: parameters[x] ) return list(parameters)
def heading(title, message)
-
Create a heading text.
Args
title
:str
- The title of the heading
message
:str
- The message that
Expand source code
def heading(title,message): """Create a heading text. Args: title (str): The title of the heading message (str): The message that """ # typer.clear() text = typer.style(title.upper(),fg=typer.colors.WHITE,bold=True) typer.echo('-'*(len(text)+2)) typer.echo(text) typer.echo('-'*(len(text)+2)) typer.echo(message+"\n") return typer
def info(message, data)
-
Display information using typer.
Args
message
:str
- Description of the information
data : The data to be displayed
Expand source code
def info(message,data): """Display information using typer. Args: message (str): Description of the information data : The data to be displayed """ message = typer.style(message,fg=typer.colors.WHITE) data = typer.style(str(data),fg=typer.colors.GREEN) typer.echo(message+": "+data)
def input_data(parameters)
-
Generates a input form based on the parameters in config.
Args
parameters
:dict
- The config parameters which will be used to generate the input fields
Returns
example
- The values for each param (key in parameters)
Expand source code
def input_data(parameters): """Generates a input form based on the parameters in config. Args: parameters (dict): The config parameters which will be used to generate the input fields Returns: example: The values for each param (key in parameters) """ example = {} types = { "INT" : int, "FLOAT" : float, "STRING" : str, } param_list = sorted( list(parameters.keys()) , key=lambda x: PRIORITY[parameters[x]['type']] ) heading("Enter input for ARgorithm","Based on argorithm parameters, input will be taken") for key in param_list: param = parameters[key] # typer.clear() info("\ninput keyword",key) info("Description",param['description']) if param["type"] == "INT": value = numeric_input(param,int) elif param["type"] == "FLOAT": value = numeric_input(param,float) elif param["type"] == "STRING": retry = True while retry: retry = False value = input_prompt("Enter string value" , type=str) retry = check_size(value,param,example) elif param["type"] == "ARRAY": retry = True while retry: retry = False value = input_prompt("Enter space separated series" , type=str).split(' ') try: value = [types[param['item-type']](x) for x in value] except: warning(f"elements must be of type {types[param['item-type']]}") retry = True retry = retry or check_size(value,param,example) elif param["type"] == "MATRIX": retry = True while retry: retry = False if isinstance(param['row'],str): row_count = example[param['row']] else: row_count = param['row'] if isinstance(param['col'],str): col_count = example[param['col']] else: col_count = param['col'] typer.echo("Enter matrix input, elements in each row must be space separated") info(f"no. of rows", row_count) info(f"no. of elements per row",col_count) value = [] for _ in range(row_count): row_value = input_prompt("",type=str).split(' ') if len(row_value) != col_count: warning(f"row must have {col_count} space separated values") retry = True try: row_value = [types[param['item-type']](x) for x in row_value] except: warning(f"elements must be of type {types[param['item-type']]}") retry = True if retry: break value.append(row_value) example[key] = value return example
def input_prompt(message, default=None, type=builtins.str, show_default=True)
-
Uses typer to create a single input field in CLI.
Args
message
:str
- The input field text
type
:type
, optional- The type of input
default
:type
, optional- The default value if user does not enter any value
show_default
:bool
, optional- By default, True. If True shows the default value to user
Returns
ip
- The data entered by user
Expand source code
def input_prompt(message,default=None,type=str,show_default=True): """Uses typer to create a single input field in CLI. Args: message (str): The input field text type (type, optional): The type of input default (type, optional): The default value if user does not enter any value show_default (bool, optional): By default, True. If True shows the default value to user Returns: ip : The data entered by user """ text = typer.style(message,fg=typer.colors.WHITE) if default: ip = typer.prompt(text,default=default,type=type,show_default=show_default) else: ip = typer.prompt(text,type=type) return ip
def master_heading()
-
Renders the ARgorithm config generator heading.
Expand source code
def master_heading(): """Renders the ARgorithm config generator heading.""" text = typer.style(config_cli_heading,fg=typer.colors.WHITE,bold=True) typer.echo(text)
def multiline()
-
takes multiline input.
Expand source code
def multiline(): """takes multiline input.""" buffer = '' while True: try: line = input() except EOFError: break if not line: break buffer += line+"\n" return buffer[:-1]
def multiline_input_prompt(message)
-
Uses typer and ARgorithmToolkit.parser.multiline to create a multiline input prompt.
Args
message
:str
- The text for prompt
Returns
ip
- data entered by user
Expand source code
def multiline_input_prompt(message): """Uses typer and ARgorithmToolkit.parser.multiline to create a multiline input prompt. Args: message (str): The text for prompt Returns: ip: data entered by user """ text = typer.style(message + ':',fg=typer.colors.WHITE) helptext = typer.style("Press ENTER on empty line to leave multiline input",fg=typer.colors.CYAN) typer.echo(text) typer.echo(helptext) ip = multiline() return ip
def numeric_input(param, input_type)
-
Initiates numeric input from user for
INT
andFLOAT
types.Args
param
:dict
- The parameter details
input_type
:[type]
- The type of numerical value
Returns
value
- value of type
input_type
Expand source code
def numeric_input(param,input_type): """Initiates numeric input from user for `INT` and `FLOAT` types. Args: param (dict): The parameter details input_type ([type]): The type of numerical value Returns: value: value of type `input_type` """ retry = True while retry: retry = False value = input_prompt("Enter integer value",type=input_type) if "start" in param: if value < param["start"]: warning(f"Please enter value larger than {param['start']}") retry = True if "end" in param: if value > param["end"]: warning(f"Please enter value less than {param['end']}") retry = True return input_type(value)
def range_input(config, parameter_name)
-
Update config with the range for
INT
andFLOAT
parameters.Args
config
:dict
- The config object where the parameter data has to be updated
parameter_name
:str
- The parameter whose metadata is being collected
Expand source code
def range_input(config,parameter_name): """Update config with the range for `INT` and `FLOAT` parameters. Args: config (dict): The config object where the parameter data has to be updated parameter_name (str): The parameter whose metadata is being collected """ range_confirm = confirm_prompt(f"Do you want to add range constraints to {parameter_name}") if range_confirm: start = input_prompt("Enter lower limit",type=int,default=-math.inf,show_default=False) if start != -math.inf: config["parameters"][parameter_name]["start"] = start end = input_prompt("Enter upper limit",type=int,default=math.inf,show_default=False) if end != math.inf: config["parameters"][parameter_name]["end"] = end return config
def size_ref(config, parameter_name, data_field)
-
Inputs size constraint for
STRING
,ARRAY
andMATRIX
parameters.Args
data_field
:str
- What is the size constraint being used as
Returns
size
- Returns size constraint
Expand source code
def size_ref(config,parameter_name,data_field): """Inputs size constraint for `STRING`,`ARRAY` and `MATRIX` parameters. Args: data_field (str): What is the size constraint being used as Returns: size: Returns size constraint """ size = input_prompt(f"Enter integer value or name of INT type parameter for {data_field}") try: size = int(size) except ValueError: if size not in config["parameters"]: info("creating INT parameter" , size) config["parameters"][size] = { "description" : f"defines {data_field} of {parameter_name} ({config['parameters'][parameter_name]['type']})", "type" : "INT" } config = range_input(config,size) config["parameters"][parameter_name][data_field] = size return config
def validateconfig(filepath)
-
Validates and stores argorithm config.
Expand source code
def validateconfig(filepath): """Validates and stores argorithm config.""" validator = Draft7Validator(CONFIG_SCHEMA) if os.path.isfile(filepath): with open(filepath,'r') as configfile: data = json.load(configfile) try: validator.validate(data) except ValidationError as ve: warning("Invalid config") errors = sorted(validator.iter_errors(data), key=lambda e: e.path) for e in errors: print(e.message) raise ve return data else: raise FileNotFoundError("No config file")
def warning(message)
-
Generate warning message using typer.
Args
message
:str
- warning text
Expand source code
def warning(message): """Generate warning message using typer. Args: message (str): warning text """ text = typer.style("⚠ " + message , fg=typer.colors.YELLOW) typer.echo(text)