def determine_missing_requirements(self):
null_return = (None, "<STR_LIT>", "<STR_LIT>")<EOL>if not hasattr(self, "<STR_LIT>"):<EOL><INDENT>_LOGGER.warning("<STR_LIT>"<EOL>"<STR_LIT>")<EOL>return null_return<EOL><DEDENT>if not self.required_inputs:<EOL><INDENT>_LOGGER.debug("<STR_LIT>")<EOL>return null_return<EOL><DEDENT>missing, empty = [], []<EOL>for file_attribute in self.required_inputs_attr:<EOL><INDENT>_LOGGER.log(<NUM_LIT:5>, "<STR_LIT>".format(file_attribute))<EOL>try:<EOL><INDENT>attval = getattr(self, file_attribute)<EOL><DEDENT>except AttributeError:<EOL><INDENT>_LOGGER.log(<NUM_LIT:5>, "<STR_LIT>",<EOL>file_attribute)<EOL>missing.append(file_attribute)<EOL>continue<EOL><DEDENT>if attval == "<STR_LIT>":<EOL><INDENT>_LOGGER.log(<NUM_LIT:5>, "<STR_LIT>",<EOL>file_attribute)<EOL>empty.append(file_attribute)<EOL><DEDENT>else:<EOL><INDENT>_LOGGER.log(<NUM_LIT:5>, "<STR_LIT>".<EOL>format(file_attribute, attval))<EOL><DEDENT><DEDENT>if missing or empty:<EOL><INDENT>reason_key = "<STR_LIT>"<EOL>reason_detail = "<STR_LIT>".format(<EOL>"<STR_LIT:U+002CU+0020>".join(missing), "<STR_LIT:U+002CU+0020>".join(empty))<EOL>return AttributeError, reason_key, reason_detail<EOL><DEDENT>missing_files = []<EOL>for paths in self.required_inputs:<EOL><INDENT>_LOGGER.log(<NUM_LIT:5>, "<STR_LIT>", paths)<EOL>for path in paths.split("<STR_LIT:U+0020>"):<EOL><INDENT>_LOGGER.log(<NUM_LIT:5>, "<STR_LIT>".format(path))<EOL>if not os.path.exists(path):<EOL><INDENT>_LOGGER.log(<NUM_LIT:5>, "<STR_LIT>".<EOL>format(path))<EOL>missing_files.append(path)<EOL><DEDENT><DEDENT><DEDENT>if not missing_files:<EOL><INDENT>return null_return<EOL><DEDENT>else:<EOL><INDENT>reason_key = "<STR_LIT>"<EOL>reason_detail = "<STR_LIT:U+002CU+0020>".join(missing_files)<EOL>return IOError, reason_key, reason_detail<EOL><DEDENT>
Determine which of this Sample's required attributes/files are missing.

:return (type, str): hypothetical exception type along with message
    about what's missing; null and empty if nothing exceptional
    is detected