[docs]classReservedChecker:_instance=None_lock=Lock()reserved_reqs_path=os.path.join(os.path.dirname(__file__),"data/reservedTags.json")def__new__(cls):ifcls._instanceisNone:withcls._lock:ifcls._instanceisNone:cls._instance=super(ReservedChecker,cls).__new__(cls)cls._instance._initialize()returncls._instancedef_initialize(self):# Load the JSON file during the first instantiationifnothasattr(self,"reserved_map"):withopen(self.reserved_reqs_path,'r')asfile:self.reserved_map=json.load(file)self._initialize_special_tags()
[docs]defcheck_reserved_compatibility(self,group,reserved_tags):""" Check to make sure that the reserved tags can be used together and no duplicates. Parameters: group (HedTagGroup): A group to be checked. reserved_tags (list of HedTag): A list of reserved tags in this group. """# Make sure there are no duplicate reserved tagsgrouped=self._get_duplicates(reserved_tags)multiples=[keyforkey,itemsingrouped.items()iflen(items)>1]iflen(multiples)>0:returnErrorHandler.format_error(ValidationErrors.HED_RESERVED_TAG_REPEATED,tag=grouped[multiples[0]][1],group=group)# Test compatibility among the reserved tagsfortaginreserved_tags:incompatible_tag=self.get_incompatible(tag,reserved_tags)ifincompatible_tag:returnErrorHandler.format_error(ValidationErrors.HED_TAGS_NOT_ALLOWED,tag=incompatible_tag[0],group=group)return[]
[docs]defcheck_tag_requirements(self,group,reserved_tags):""" Check the tag requirements within the group. Parameters: group (HedTagGroup): A group to be checked. reserved_tags (list of HedTag): A list of reserved tags in this group. Notes: This is only called when there are some reserved incompatible tags. """[requires_defs,defs]=self.get_def_information(group,reserved_tags)iflen(requires_defs)>1:returnErrorHandler.format_error(ValidationErrors.HED_RESERVED_TAG_REPEATED,tag=requires_defs[0],group=group)iflen(requires_defs)==1andlen(defs)!=1:returnErrorHandler.format_error(TemporalErrors.ONSET_NO_DEF_TAG_FOUND,tag=requires_defs[0])iflen(requires_defs)==0andlen(defs)!=0:returnErrorHandler.format_error(ValidationErrors.HED_TAGS_NOT_ALLOWED,tag=reserved_tags[0],group=group)other_tags=[tagfortagingroup.tags()iftagnotinreserved_tagsandtagnotindefs]iflen(other_tags)>0:returnErrorHandler.format_error(ValidationErrors.HED_TAGS_NOT_ALLOWED,tag=other_tags[0],group=group)# Check the subgroup requirementsother_groups=[groupforgroupingroup.groups()ifgroupnotindefs]min_allowed,max_allowed=self.get_group_requirements(reserved_tags)ifnotmath.isinf(max_allowed)andlen(other_groups)>max_allowed:returnErrorHandler.format_error(ValidationErrors.HED_RESERVED_TAG_GROUP_ERROR,group=group,group_count=str(len(other_groups)),tag_list=reserved_tags)ifgroup.is_groupandnotmath.isinf(max_allowed)andmin_allowed>len(other_groups):returnErrorHandler.format_error(ValidationErrors.HED_RESERVED_TAG_GROUP_ERROR,group=group,group_count=str(len(other_groups)),tag_list=reserved_tags)return[]
[docs]defget_group_requirements(self,reserved_tags)->tuple[float,float]:""" Returns the maximum and minimum number of groups required for these reserved tags. Parameters: reserved_tags (list of HedTag): The reserved tags to be checked. Returns: tuple[float, float]: the maximum required and the minimum required. """max_allowed=float('inf')min_allowed=float('-inf')fortaginreserved_tags:requirements=self.reserved_map[tag.short_base_tag]this_min=requirements['minNonDefSubgroups']ifthis_minisnotNoneandthis_min>min_allowed:min_allowed=this_minthis_max=requirements['maxNonDefSubgroups']ifthis_maxisnotNoneandthis_max<max_allowed:max_allowed=this_maxifmax_allowed<min_allowedandlen(reserved_tags)>1:min_allowed=max_allowedreturnmin_allowed,max_allowed
[docs]defget_def_information(self,group,reserved_tags)->list[list]:"""Get definition information for reserved tags. Parameters: group (HedGroup): The HED group to check. reserved_tags (list of HedTag): The reserved tags to process. Returns: list[list]: A list containing [requires_defs, defs]. """requires_defs=[tagfortaginreserved_tagsiftag.short_base_taginself.requires_def_tags]defs=group.find_def_tags(recursive=False,include_groups=1)return[requires_defs,defs]
[docs]defget_incompatible(self,tag,reserved_tags)->list:""" Return the list of tags that cannot be in the same group with tag. Parameters: tag (HedTag): Reserved tag to be tested. reserved_tags (list of HedTag): Reserved tags (no duplicates). Returns: list[HedTag]: List of incompatible tags. """requirements=self.reserved_map[tag.short_base_tag]other_allowed=requirements["otherAllowedNonDefTags"]incompatible=[this_tagforthis_taginreserved_tagsifthis_tag.short_base_tagnotinother_allowedandthis_tag!=tag]returnincompatible
# Additional methods for other checks should be implemented here following similar patterns.if__name__=="__main__":checker=ReservedChecker.get_instance()print("ReservedChecker initialized successfully.")print(checker.special_names)