def validate(nanopub: dict, error_level: str = "<STR_LIT>") -> Tuple[str, str, str]:
<EOL>v = []<EOL>bel_version = config["<STR_LIT>"]["<STR_LIT>"]["<STR_LIT>"]<EOL>try:<EOL><INDENT>if not isinstance(nanopub["<STR_LIT>"]["<STR_LIT>"], list):<EOL><INDENT>msg = "<STR_LIT>"<EOL>v.append(<EOL>{<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:label>": "<STR_LIT>",<EOL>"<STR_LIT>": msg,<EOL>"<STR_LIT>": msg,<EOL>}<EOL>)<EOL><DEDENT><DEDENT>except Exception as e:<EOL><INDENT>msg = '<STR_LIT>'<EOL>v.append(<EOL>{<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:label>": "<STR_LIT>",<EOL>"<STR_LIT>": msg,<EOL>"<STR_LIT>": msg,<EOL>}<EOL>)<EOL><DEDENT>try:<EOL><INDENT>if (<EOL>"<STR_LIT:name>" in nanopub["<STR_LIT>"]["<STR_LIT:type>"]<EOL>and "<STR_LIT:version>" in nanopub["<STR_LIT>"]["<STR_LIT:type>"]<EOL>):<EOL><INDENT>pass<EOL><DEDENT>if nanopub["<STR_LIT>"]["<STR_LIT:type>"]["<STR_LIT:name>"].upper() == "<STR_LIT>":<EOL><INDENT>bel_version = nanopub["<STR_LIT>"]["<STR_LIT:type>"]["<STR_LIT:version>"]<EOL><DEDENT><DEDENT>except Exception as e:<EOL><INDENT>msg = '<STR_LIT>'<EOL>v.append(<EOL>{<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:label>": "<STR_LIT>",<EOL>"<STR_LIT>": msg,<EOL>"<STR_LIT>": msg,<EOL>}<EOL>)<EOL><DEDENT>try:<EOL><INDENT>for key in ["<STR_LIT>", "<STR_LIT>", "<STR_LIT>"]:<EOL><INDENT>if key in nanopub["<STR_LIT>"]["<STR_LIT>"]:<EOL><INDENT>break<EOL><DEDENT><DEDENT>else:<EOL><INDENT>msg = '<STR_LIT>'<EOL>v.append(<EOL>{<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:label>": "<STR_LIT>",<EOL>"<STR_LIT>": msg,<EOL>"<STR_LIT>": msg,<EOL>}<EOL>)<EOL><DEDENT><DEDENT>except Exception as e:<EOL><INDENT>msg = '<STR_LIT>'<EOL>v.append(<EOL>{<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:label>": "<STR_LIT>",<EOL>"<STR_LIT>": msg,<EOL>"<STR_LIT>": msg,<EOL>}<EOL>)<EOL><DEDENT>if "<STR_LIT>" in nanopub["<STR_LIT>"]:<EOL><INDENT>for idx, assertion in enumerate(nanopub["<STR_LIT>"]["<STR_LIT>"]):<EOL><INDENT>bo = bel.lang.belobj.BEL(<EOL>bel_version, config["<STR_LIT>"]["<STR_LIT>"]["<STR_LIT>"]<EOL>)<EOL>belstr = f'<STR_LIT>'<EOL>belstr = belstr.replace("<STR_LIT:None>", "<STR_LIT>")<EOL>try:<EOL><INDENT>messages = (<EOL>bo.parse(belstr)<EOL>.semantic_validation(error_level=error_level)<EOL>.validation_messages<EOL>)<EOL>for message in messages:<EOL><INDENT>(level, msg) = message<EOL>if error_level == "<STR_LIT>":<EOL><INDENT>if level == "<STR_LIT>":<EOL><INDENT>v.append(<EOL>{<EOL>"<STR_LIT>": f"<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:label>": f"<STR_LIT>",<EOL>"<STR_LIT:index>": idx,<EOL>"<STR_LIT>": msg,<EOL>"<STR_LIT>": convert_msg_to_html(msg),<EOL>}<EOL>)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>v.append(<EOL>{<EOL>"<STR_LIT>": f"<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:label>": f"<STR_LIT>",<EOL>"<STR_LIT:index>": idx,<EOL>"<STR_LIT>": msg,<EOL>"<STR_LIT>": convert_msg_to_html(msg),<EOL>}<EOL>)<EOL><DEDENT><DEDENT><DEDENT>except Exception as e:<EOL><INDENT>msg = f"<STR_LIT>"<EOL>v.append(<EOL>{<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:label>": "<STR_LIT>",<EOL>"<STR_LIT:index>": idx,<EOL>"<STR_LIT>": msg,<EOL>"<STR_LIT>": msg,<EOL>}<EOL>)<EOL>log.exception(f"<STR_LIT>")<EOL><DEDENT><DEDENT><DEDENT>if error_level == "<STR_LIT>":<EOL><INDENT>for idx, annotation in enumerate(nanopub["<STR_LIT>"].get("<STR_LIT>", [])):<EOL><INDENT>term_type = annotation["<STR_LIT:type>"]<EOL>term_id = annotation["<STR_LIT:id>"]<EOL>log.info(f"<STR_LIT>")<EOL>search_body = {<EOL>"<STR_LIT>": ["<STR_LIT>", "<STR_LIT:id>", "<STR_LIT:name>", "<STR_LIT:label>", "<STR_LIT>"],<EOL>"<STR_LIT>": {"<STR_LIT>": {"<STR_LIT:id>": term_id}},<EOL>}<EOL>results = es.search(index="<STR_LIT>", doc_type="<STR_LIT>", body=search_body)<EOL>if len(results["<STR_LIT>"]["<STR_LIT>"]) > <NUM_LIT:0>:<EOL><INDENT>result = results["<STR_LIT>"]["<STR_LIT>"][<NUM_LIT:0>]["<STR_LIT>"]<EOL>if term_type not in result["<STR_LIT>"]:<EOL><INDENT>msg = f'<STR_LIT>'<EOL>v.append(<EOL>{<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:index>": idx,<EOL>"<STR_LIT:label>": "<STR_LIT>",<EOL>"<STR_LIT>": msg,<EOL>"<STR_LIT>": msg,<EOL>}<EOL>)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>msg = f"<STR_LIT>"<EOL>v.append(<EOL>{<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:index>": idx,<EOL>"<STR_LIT:label>": "<STR_LIT>",<EOL>"<STR_LIT>": msg,<EOL>"<STR_LIT>": msg,<EOL>}<EOL>)<EOL><DEDENT><DEDENT><DEDENT>return v<EOL>
Validate Nanopub

    Error Levels are similar to log levels - selecting WARNING includes both
    WARNING and ERROR, selecting ERROR just includes ERROR

    The validation result is a list of objects containing
        {
            'level': 'Warning|Error',
            'section': 'Assertion|Annotation|Structure',
            'label': '{Error|Warning}-{Assertion|Annotation|Structure}',  # to be used for faceting in Elasticsearch
            'index': idx,  # Index of Assertion or Annotation in Nanopub - starts at 0
            'msg': msg,  # Error or Warning message
        }

    Args:
        nanopub: nanopub record starting with nanopub...
        level: return WARNING or just ERROR?  defaults to warnings and errors
    Returns:
        list(tuples): [{'level': 'Warning', 'section': 'Assertion', 'label': 'Warning-Assertion', 'index': 0, 'msg': <msg>}]