Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def parse_group_action(section, line, config, section_name):
"""parse a group action, either FIELD or SPLIT, which must belong to
either a fields or values section.
Parameters
=========
section: a valid section name from the deid config file
line: the line content to parse for the section/action
config: the growing/current config dictionary
section_name: optionally, a section name
"""
if not line.upper().startswith(group_actions):
bot.exit("%s is not a valid group action." % line)
if not line.upper().startswith("FIELD") and section == "fields":
bot.exit("%fields only supports FIELD actions.")
# We may have to deal with cases of spaces
bot.debug("%s: adding %s" % (section, line))
parts = line.split(" ")
action = parts.pop(0).replace(" ", "")
# Both require some parts
if not parts:
bot.exit("%s action %s requires additional arguments" % (section, action))
# For both, the second is always a field or field expander
field = parts.pop(0)
# Fields supports one or more fields with expanders (no third arguments)
if section == "fields":
config[section][section_name].append({"action": action, "field": field})
# Default values for split are length 1 and character empty space
bot.debug("Parsing action %s" % action)
split_by = " "
minlength = 1
if "value" in action:
for param in action["value"].split(";"):
param_name, param_val = param.split("=")
param_name = param_name.strip()
param_val = param_val.strip()
# Set a custom parameter legnth
if param_name == "minlength":
minlength = int(param_val)
bot.debug("Minimum length set to %s" % minlength)
elif param_name == "by":
split_by = param_val.strip("'").strip('"')
bot.debug("Splitting value set to %s" % split_by)
for uid, field in subset.items():
new_values = (str(field.element.value) or "").split(split_by)
for new_value in new_values:
if len(new_value) >= minlength:
values.add(new_value)
else:
bot.warning(
"Unrecognized action %s for values list extraction." % action["action"]
)
return list(values)
"""
# A default deid will be loaded if all else fails
default_deid = os.path.join(get_installdir(), "data", "deid.dicom")
if path is None:
path = os.getcwd()
# The user has provided a directory
if os.path.isdir(path):
contenders = [
"%s/%s" % (path, x) for x in os.listdir(path) if x.startswith("deid")
]
if len(contenders) == 0:
bot.warning(
"No deid settings files found in %s, will use default dicom.deid."
% path
)
contenders.append(default_deid)
elif len(contenders) > 1:
bot.warning("Multiple deid files found in %s, will use first." % (path))
path = contenders[0]
# We have a file path at this point
if not os.path.exists(path):
bot.exit("Cannot find deid file %s, exiting." % (path))
return path
def parse_value(item,value):
'''parse_value will parse the value field of an action,
either returning the string, or a variable looked up
in the case of var:FieldName
'''
# Does the user want a custom value?
if re.search('[:]',value):
value_type,value_option = value.split(':')
if value_type.lower() == "var":
# If selected variable not provided, skip
if value_option not in item:
return None
return item[value_option]
bot.warning('%s is not a valid value type, skipping.' %(value_type))
return None
return value
# Does the user want a custom value?
if re.search("[:]", value):
value_type, value_option = value.split(":", 1)
if value_type.lower() == "var":
# If selected variable not provided, skip
if value_option not in item:
return None
return item[value_option]
# The user is providing a specific function
elif value_type.lower() == "func":
if value_option not in item:
bot.warning("%s not found in item lookup." % (value_option))
return None
# item is the lookup, value from the recipe, and field
# The field is an entire dicom element object
return item[value_option](dicom=dicom, value=value, field=field, item=item)
bot.warning("%s is not a valid value type, skipping." % (value_type))
return None
return value
# The user has provided a directory
if os.path.isdir(path):
contenders = [
"%s/%s" % (path, x) for x in os.listdir(path) if x.startswith("deid")
]
if len(contenders) == 0:
bot.warning(
"No deid settings files found in %s, will use default dicom.deid."
% path
)
contenders.append(default_deid)
elif len(contenders) > 1:
bot.warning("Multiple deid files found in %s, will use first." % (path))
path = contenders[0]
# We have a file path at this point
if not os.path.exists(path):
bot.exit("Cannot find deid file %s, exiting." % (path))
return path
Parameters
==========
tag: the text that comes after deid to indicate the tag of the file in deid/data
exit_on_fail: if None is an acceptable return value, this should be set to False
(default is True).
quiet: Default False. If None is acceptable, quiet can be set to True
load: also load the deid, if resulting path (from path or tag) is not None
"""
# no tag/path means load default
if tag is None:
tag = "dicom"
# If it's already loaded
if isinstance(tag, dict):
bot.debug("deid is already loaded.")
return tag
# If it's a path, get full path
if os.path.exists(tag):
deid = os.path.abspath(tag)
else:
deid = "%s/deid.%s" % (data_base, tag)
if not os.path.exists(deid):
if quiet is False:
bot.error("Cannot find %s" % (deid))
if exit_on_fail is True:
sys.exit(1)
else:
return None
bot.exit("%s is not a valid action line." % line)
# We may have to deal with cases of spaces
parts = line.split(" ")
action = parts.pop(0).replace(" ", "")
# What field is the action for?
if len(parts) < 1:
bot.exit("%s requires a FIELD value, but not found." % action)
field = parts.pop(0)
# Actions that require a value
if action in ["ADD", "REPLACE", "JITTER"]:
if len(parts) == 0:
bot.exit("%s requires a VALUE, but not found" % action)
value = _remove_comments(parts)
bot.debug("%s: adding %s" % (section, line))
config[section].append({"action": action, "field": field, "value": value})
# Actions that can optionally have a value
elif action in ["REMOVE"]:
bot.debug("%s: adding %s" % (section, line))
# Case 1: removing without any criteria
if len(parts) == 0:
config[section].append({"action": action, "field": field})
# Case 2: REMOVE can have a func:is_thing to return boolean
else:
value = _remove_comments(parts)
"""add section will add a section (and optionally)
section name to a config
Parameters
==========
config: the config (dict) parsed thus far
section: the section name to add
section_name: an optional name, added as a level
"""
if section is None:
bot.exit("You must define a section (e.g. %header) before any action.")
if section in ["filter", "values", "fields"] and section_name is None:
bot.exit("You must provide a name for a filter section.")
if section not in sections:
bot.exit("%s is not a valid section." % section)
if section not in config:
# If a section is named, we have more one level (dict)
if section_name is not None:
config[section] = OrderedDict()
config[section][section_name] = []
bot.debug("Adding section %s %s" % (section, section_name))
else:
config[section] = []
bot.debug("Adding section %s" % section)
return config
def add_section(config, section, section_name=None):
"""add section will add a section (and optionally)
section name to a config
Parameters
==========
config: the config (dict) parsed thus far
section: the section name to add
section_name: an optional name, added as a level
"""
if section is None:
bot.exit("You must define a section (e.g. %header) before any action.")
if section in ["filter", "values", "fields"] and section_name is None:
bot.exit("You must provide a name for a filter section.")
if section not in sections:
bot.exit("%s is not a valid section." % section)
if section not in config:
# If a section is named, we have more one level (dict)
if section_name is not None:
config[section] = OrderedDict()
config[section][section_name] = []
bot.debug("Adding section %s %s" % (section, section_name))
else:
config[section] = []