def test(self): filename = os.path.join(self.FIXTURE_DIR, 'LEMS_NML2_Ex5_DetCell.xml') errors, warnings, _ = validate_model(filename) print(flatten_nested_list_of_strings(errors)) self.assertEqual(errors, []) self.assertEqual(warnings, []) filename = os.path.join(self.FIXTURE_DIR, 'no-simulation.xml') errors, warnings, _ = validate_model(filename) self.assertIn("No component found: sim1", flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) filename = os.path.join(self.FIXTURE_DIR, 'undefined-target.xml') errors, warnings, _ = validate_model(filename) self.assertIn("No component found: net2", flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) filename = os.path.join(self.FIXTURE_DIR, 'missing-include.xml') errors, warnings, _ = validate_model(filename) self.assertIn("Can't find file at path: Cells2.xml", flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) filename = os.path.join(self.FIXTURE_DIR, 'invalid.xml') errors, warnings, _ = validate_model(filename) self.assertIn("Can't read LEMS from XMLElt", flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, [])
def test(self): filename = os.path.join(self.FIXTURE_DIRNAME, 'Escherichia-coli-K12-WT.zip') errors, warnings, model = validation.validate_model(filename) self.assertEqual(errors, []) self.assertEqual(warnings, []) self.assertIsInstance(model, rba.model.RbaModel) filename = None errors, warnings, model = validation.validate_model(filename) self.assertIn('is not a path', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) self.assertEqual(model, None) filename = os.path.join(self.FIXTURE_DIRNAME, 'not exist.zip') errors, warnings, model = validation.validate_model(filename) self.assertIn('does not exist', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) self.assertEqual(model, None) filename = __file__ errors, warnings, model = validation.validate_model(filename) self.assertIn('is not a valid RBA', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) self.assertEqual(model, None) filename = os.path.join(self.FIXTURE_DIRNAME, 'Escherichia-coli-K12-WT-invalid.zip') errors, warnings, model = validation.validate_model(filename) self.assertIn('is not a valid RBA', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) self.assertEqual(model, None)
def validate_archive(self, filename): reader = CombineArchiveReader() name = os.path.relpath(filename, EXAMPLES_DIR) temp_dirname = os.path.join(self.temp_dirname, name) if not os.path.isdir(temp_dirname): os.makedirs(temp_dirname) archive = reader.run(filename, temp_dirname) config = Config( OMEX_METADATA_SCHEMA=OmexMetadataSchema.biosimulations, ) error_msgs, warning_msgs = validate( archive, temp_dirname, formats_to_validate=list( CombineArchiveContentFormat.__members__.values()), config=config, ) if warning_msgs: msg = 'The COMBINE/OMEX archive may be invalid.\n {}'.format( flatten_nested_list_of_strings(warning_msgs).replace( '\n', '\n ')) warnings.warn(msg, BioSimulatorsWarning) if error_msgs: msg = 'The COMBINE/OMEX archive is not valid.\n {}'.format( flatten_nested_list_of_strings(error_msgs).replace( '\n', '\n ')) raise ValueError(msg)
def test_flatten_nested_list_of_strings(self): self.assertEqual( utils.flatten_nested_list_of_strings([['A'], ['B'], ['C']], prefix='- ', indent=' '), '\n'.join([ '- A', '- B', '- C', ])) self.assertEqual( utils.flatten_nested_list_of_strings( [['A'], [ 'B', [ ['1'], ['2'], ['3'], ], ], ['C']], prefix='- ', indent=' '), '\n'.join([ '- A', '- B', ' - 1', ' - 2', ' - 3', '- C', ])) self.assertEqual( utils.flatten_nested_list_of_strings([['A'], [ 'B', [ ['1'], [ '2\n3', [ ['i'], ['ii\niii'], ], ], ['4'], ], ], ['C']], prefix='- ', indent=' '), '\n'.join([ '- A', '- B', ' - 1', ' - 2', ' 3', ' - i', ' - ii', ' iii', ' - 4', '- C', ]))
def test_BiosimulationsOmexMetaReader_get_combine_archive_uri_no_root(self): rdf, errors, warnings = io.BiosimulationsOmexMetaReader.read_rdf(self.NO_ROOT_FIXTURE) triples = io.BiosimulationsOmexMetaReader.get_rdf_triples(rdf) root_uri, errors, warnings = io.BiosimulationsOmexMetaReader.get_combine_archive_uri(triples) self.assertEqual(root_uri, '.') self.assertIn('does not contain metadata', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) _, errors, warnings = io.BiosimulationsOmexMetaReader().run(self.NO_ROOT_FIXTURE) self.assertIn('does not contain metadata', flatten_nested_list_of_strings(errors))
def test_BiosimulationsOmexMetaReader_get_combine_archive_uri_multiple_root(self): rdf, errors, warnings = io.BiosimulationsOmexMetaReader.read_rdf(self.MULTIPLE_ROOTS_FIXTURE) triples = io.BiosimulationsOmexMetaReader.get_rdf_triples(rdf) root_uri, errors, warnings = io.BiosimulationsOmexMetaReader.get_combine_archive_uri(triples) self.assertEqual(root_uri, None) self.assertIn('metadata about multiple', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) _, errors, warnings = io.BiosimulationsOmexMetaReader().run(self.MULTIPLE_ROOTS_FIXTURE) self.assertIn('metadata about multiple OMEX archives', flatten_nested_list_of_strings(errors))
def test_read_omex_meta_file(self): triples, errors, warnings = io.read_omex_meta_file( self.FIXTURE, config=Config( OMEX_METADATA_SCHEMA=data_model.OmexMetadataSchema.rdf_triples, )) self.assertEqual(errors, []) self.assertEqual(warnings, []) metadata, errors, warnings = io.read_omex_meta_file( self.FIXTURE, config=Config( OMEX_METADATA_SCHEMA=data_model.OmexMetadataSchema.biosimulations, ), working_dir=self.dir_name) self.assertEqual(errors, []) self.assertEqual(warnings, []) metadata, errors, warnings = io.read_omex_meta_file( self.FIXTURE, config=Config( OMEX_METADATA_SCHEMA=None, )) self.assertEqual(metadata, None) self.assertIn('is not supported', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, [])
def test_TriplesOmexMetaReader_run(self): triples, errors, warnings = io.TriplesOmexMetaReader().run(self.FIXTURE) self.assertEqual(errors, []) self.assertEqual(warnings, []) triples, errors, warnings = io.TriplesOmexMetaReader().run([self.FIXTURE]) self.assertEqual(errors, []) self.assertEqual(warnings, []) triples, errors, warnings = io.TriplesOmexMetaReader().run('undefined') self.assertIn('is not a file', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) triples, errors, warnings = io.TriplesOmexMetaReader().run(['undefined']) self.assertIn('is not a file', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, [])
def test_validate_omex_meta_file(self): config = Config(OMEX_METADATA_SCHEMA=OmexMetadataSchema.rdf_triples) _, errors, warnings = read_omex_meta_file(os.path.join( self.OMEX_META_FIXTURES_DIR, 'libcombine.rdf'), working_dir=self.tmp_dir, config=config) self.assertEqual(errors, []) self.assertEqual(warnings, []) _, errors, warnings = read_omex_meta_file(os.path.join( self.OMEX_META_FIXTURES_DIR, 'biosimulations.rdf'), working_dir=self.tmp_dir, config=config) self.assertEqual(errors, []) self.assertEqual(warnings, []) _, errors, warnings = read_omex_meta_file(os.path.join( self.OMEX_META_FIXTURES_DIR, 'warning.rdf'), working_dir=self.tmp_dir, config=config) self.assertIn("Unsupported version '1.2'", flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) _, errors, warnings = read_omex_meta_file(os.path.join( self.OMEX_META_FIXTURES_DIR, 'invalid.rdf'), working_dir=self.tmp_dir, config=config) self.assertEqual(len(errors), 4) self.assertIn("XML parser error", flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) _, errors, warnings = read_omex_meta_file(os.path.join( self.OMEX_META_FIXTURES_DIR, 'malformed.rdf'), working_dir=self.tmp_dir, config=config) self.assertEqual(len(errors), 3) self.assertIn("Opening and ending tag mismatch", flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, [])
def test_manifest_in_manifest(self): out_dir = os.path.join(self.tmp_dir, 'out') archive = CombineArchiveReader().run( os.path.join(os.path.dirname(__file__), '..', 'fixtures', 'manifest-in-manifest.omex'), out_dir) errors, warnings = validate(archive, out_dir) self.assertEqual(errors, []) self.assertIn( 'manifests should not contain content entries for themselves', flatten_nested_list_of_strings(warnings)) out_dir = os.path.join(self.tmp_dir, 'out') archive = CombineArchiveReader().run( os.path.join(os.path.dirname(__file__), '..', 'fixtures', 'multiple-manifests.omex'), out_dir) errors, warnings = validate(archive, out_dir) self.assertEqual(errors, []) self.assertIn( 'manifests should not contain content entries for themselves', flatten_nested_list_of_strings(warnings))
def test_validate(self): os.remove(os.path.join(self.tmp_dir, 'thumbnail.png')) archive = CombineArchiveReader().run(self.OMEX_FIXTURE, self.tmp_dir) errors, warnings = validate(archive, self.tmp_dir) self.assertEqual(errors, []) self.assertNotEqual(warnings, []) archive2 = copy.deepcopy(archive) for content in archive.contents: archive2.contents.append(content) errors, warnings = validate(archive2, self.tmp_dir) self.assertIn('contains repeated content items', flatten_nested_list_of_strings(errors)) archive2 = copy.deepcopy(archive) archive2.contents = [] errors, warnings = validate(archive2, self.tmp_dir) self.assertIn('does not contain content items', flatten_nested_list_of_strings(errors))
def test_read_rdf(self): rdf, errors, warnings = io.OmexMetaReader.read_rdf(self.FIXTURE) self.assertIsInstance(rdf, pyomexmeta.RDF) self.assertEqual(errors, []) self.assertEqual(warnings, []) rdf, errors, warnings = io.OmexMetaReader.read_rdf('undefined') self.assertEqual(rdf, None) self.assertIn('is not a file', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) rdf, errors, warnings = io.OmexMetaReader.read_rdf(self.INVALID_FIXTURE) self.assertEqual(rdf, None) self.assertIn('XML parser error', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) rdf, errors, warnings = io.OmexMetaReader.read_rdf(self.WARNING_FIXTURE) self.assertEqual(rdf, None) self.assertIn('Unsupported version', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, [])
def test(self): errors, warnings, _ = validate_model( os.path.join(self.FIXTURE_DIR, 'bounce1.txt')) self.assertEqual(errors, []) self.assertEqual(warnings, []) errors, warnings, _ = validate_model( os.path.join(self.FIXTURE_DIR, 'invalid.txt')) self.assertIn("not a valid Smoldyn", flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) errors, warnings, _ = validate_model( os.path.join(self.FIXTURE_DIR, 'not a file.txt')) self.assertIn('is not a file', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) errors, warnings, _ = validate_model(None) self.assertIn('must be a path', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, [])
def test(self): errors, warnings, _ = validate_model( os.path.join(self.FIXTURE_DIR, 'valid.bngl')) self.assertEqual(errors, []) self.assertEqual(warnings, []) fid, filename = tempfile.mkstemp() os.close(fid) shutil.copyfile(os.path.join(self.FIXTURE_DIR, 'valid.bngl'), filename) errors, warnings, _ = validate_model(filename) self.assertEqual(errors, []) self.assertEqual(warnings, []) os.remove(filename) filename = os.path.join(self.FIXTURE_DIR, 'invalid.bngl2') _, errors, _ = read_model(filename, '') self.assertIn("not a valid BNGL or BGNL XML file", flatten_nested_list_of_strings(errors)) filename = os.path.join(self.FIXTURE_DIR, 'invalid.bngl') errors, warnings, _ = validate_model(filename) self.assertIn("not a valid BNGL", flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) filename = os.path.join(self.FIXTURE_DIR, 'does-not-exist') errors, warnings, _ = validate_model(filename) self.assertIn('is not a file', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) filename = None errors, warnings, _ = validate_model(filename) self.assertIn('must be a path', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) filename = os.path.join(self.FIXTURE_DIR, '..', 'BIOMD0000000075.xml') errors, warnings, _ = validate_model(filename) self.assertIn('does not appear to a valid', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, [])
def test_validate_biosimulations_metadata_for_uri(self): config = Config( OMEX_METADATA_SCHEMA=data_model.OmexMetadataSchema.biosimulations) md, errors, _ = read_omex_meta_file( [self.FIXTURE_THIRD_A, self.FIXTURE_THIRD_B, self.FIXTURE_THIRD_C], config=config) self.assertEqual(errors, []) self.assertEqual(len(md), 2) md, errors, _ = read_omex_meta_file( [self.FIXTURE_THIRD_A, self.FIXTURE_THIRD_B], config=config) self.assertEqual(errors, []) self.assertEqual(len(md), 1) md, errors, _ = read_omex_meta_file( [self.FIXTURE_THIRD_A, self.FIXTURE_THIRD_C], config=config) self.assertEqual(errors, []) self.assertEqual(len(md), 2) md, errors, _ = read_omex_meta_file( [self.FIXTURE_THIRD_B, self.FIXTURE_THIRD_C], config=config) self.assertIn('is required', flatten_nested_list_of_strings(errors)) self.assertEqual(len(md), 2) md, errors, _ = read_omex_meta_file([self.FIXTURE_THIRD_A], config=config) self.assertEqual(errors, []) self.assertEqual(len(md), 1) md, errors, _ = read_omex_meta_file([self.FIXTURE_THIRD_B], config=config) self.assertIn('is required', flatten_nested_list_of_strings(errors)) self.assertEqual(len(md), 1) md, errors, _ = read_omex_meta_file([self.FIXTURE_THIRD_C], config=config) self.assertIn('does not contain information', flatten_nested_list_of_strings(errors)) self.assertEqual(len(md), 1)
def test_read_omex_meta_files_for_archive(self): shutil.copyfile(os.path.join(self.FIXTURE_DIR, 'biosimulations.rdf'), os.path.join(self.dir_name, 'biosimulations.rdf')) shutil.copyfile(os.path.join(self.FIXTURE_DIR, 'biosimulations-with-file-annotations.rdf'), os.path.join(self.dir_name, 'biosimulations-with-file-annotations.rdf')) archive = CombineArchive() archive.contents = [ CombineArchiveContent( location='biosimulations.rdf', format=CombineArchiveContentFormat.OMEX_METADATA, ), CombineArchiveContent( location='biosimulations-with-file-annotations.rdf', format=CombineArchiveContentFormat.OMEX_METADATA, ), ] config = Config( OMEX_METADATA_SCHEMA=data_model.OmexMetadataSchema.biosimulations, ) md, errors, warnings = io.read_omex_meta_files_for_archive( archive, self.dir_name, config=config) self.assertIn('The COMBINE archive should only contain one instance of predicate', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) self.assertEqual(len(md), 2) self.assertEqual(sorted(m['uri'] for m in md), sorted(['.', './sim.sedml/figure1'])) md, errors, warnings = io.read_omex_meta_files_for_archive(archive, self.dir_name) self.assertIn('The COMBINE archive should only contain one instance of predicate', flatten_nested_list_of_strings(errors)) shutil.copyfile(os.path.join(self.FIXTURE_DIR, 'biosimulations-abbrev-third-a.rdf'), os.path.join(self.dir_name, 'biosimulations-abbrev-third-a.rdf')) shutil.copyfile(os.path.join(self.FIXTURE_DIR, 'biosimulations-abbrev-third-b.rdf'), os.path.join(self.dir_name, 'biosimulations-abbrev-third-b.rdf')) shutil.copyfile(os.path.join(self.FIXTURE_DIR, 'biosimulations-abbrev-third-c.rdf'), os.path.join(self.dir_name, 'biosimulations-abbrev-third-c.rdf')) archive = CombineArchive() archive.contents = [ CombineArchiveContent( location='biosimulations-abbrev-third-a.rdf', format=CombineArchiveContentFormat.OMEX_METADATA, ), CombineArchiveContent( location='biosimulations-abbrev-third-b.rdf', format=CombineArchiveContentFormat.OMEX_METADATA, ), CombineArchiveContent( location='biosimulations-abbrev-third-c.rdf', format=CombineArchiveContentFormat.OMEX_METADATA, ), ] config = Config( OMEX_METADATA_SCHEMA=data_model.OmexMetadataSchema.biosimulations, ) md, errors, warnings = io.read_omex_meta_files_for_archive( archive, self.dir_name, config=config) self.assertEqual(errors, []) self.assertEqual(warnings, []) self.assertEqual(len(md), 2) self.assertEqual(sorted(m['uri'] for m in md), sorted(['.', './sim.sedml/figure1']))
def test_no_validation(self): archive_dirname = os.path.join(self.tmp_dir, 'archive') os.mkdir(archive_dirname) # OMEX manifests archive = CombineArchive() errors, warnings = validate(archive, archive_dirname) self.assertIn('must have at least one content', flatten_nested_list_of_strings(errors)) self.assertNotEqual(warnings, []) with mock.patch.dict('os.environ', {'VALIDATE_OMEX_MANIFESTS': '0'}): errors, warnings = validate(archive, archive_dirname) self.assertEqual(errors, []) self.assertEqual(warnings, []) # SED-ML archive = CombineArchive() archive.contents.append( CombineArchiveContent( location='simulation.sedml', format=CombineArchiveContentFormat.SED_ML.value, )) sedml_filename = os.path.join(archive_dirname, 'simulation.sedml') with open(sedml_filename, 'w') as file: file.write('invalid') errors, warnings = validate(archive, archive_dirname) self.assertIn('Missing XML declaration', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) with mock.patch.dict('os.environ', { 'VALIDATE_OMEX_MANIFESTS': '0', 'VALIDATE_SEDML': '0', }): errors, warnings = validate(archive, archive_dirname) self.assertEqual(errors, []) self.assertEqual(warnings, []) os.remove(sedml_filename) # models archive = CombineArchive() archive.contents.append( CombineArchiveContent( location='simulation.sedml', format=CombineArchiveContentFormat.SED_ML.value, )) model_filename = os.path.join(archive_dirname, 'model.xml') shutil.copyfile( os.path.join(os.path.dirname(__file__), '..', 'fixtures', 'BIOMD0000000297.xml'), model_filename) sed_doc = SedDocument() sed_doc.models.append( Model(id='model', source=model_filename, language=ModelLanguage.SBML.value)) sedml_filename = os.path.join(archive_dirname, 'simulation.sedml') SedmlSimulationWriter().run(sed_doc, sedml_filename) with open(model_filename, 'w') as file: file.write('invalid') errors, warnings = validate(archive, archive_dirname) self.assertIn('Missing XML declaration', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) with mock.patch.dict('os.environ', { 'VALIDATE_OMEX_MANIFESTS': '0', 'VALIDATE_SEDML_MODELS': '0', }): errors, warnings = validate(archive, archive_dirname) self.assertEqual(errors, []) self.assertEqual(warnings, []) os.remove(sedml_filename) os.remove(model_filename) # images archive = CombineArchive() archive.contents.append( CombineArchiveContent( location='image.png', format=CombineArchiveContentFormat.PNG.value, )) errors, warnings = validate( archive, archive_dirname, formats_to_validate=[CombineArchiveContentFormat.PNG]) self.assertIn('The PNG file at location `image.png` is invalid.', flatten_nested_list_of_strings(errors)) self.assertNotEqual(warnings, []) with mock.patch.dict('os.environ', { 'VALIDATE_OMEX_MANIFESTS': '0', 'VALIDATE_IMAGES': '0', }): errors, warnings = validate( archive, archive_dirname, formats_to_validate=[CombineArchiveContentFormat.PNG]) self.assertEqual(errors, []) self.assertEqual(warnings, []) # OMEX metadata archive = CombineArchive() archive.contents.append( CombineArchiveContent( location='metadata.rdf', format=CombineArchiveContentFormat.OMEX_METADATA.value, )) metadata_file = os.path.join(archive_dirname, 'metadata.rdf') shutil.copyfile( os.path.join(os.path.dirname(__file__), '..', 'fixtures', 'omex-metadata', 'invalid.rdf'), metadata_file) errors, warnings = validate( archive, archive_dirname, formats_to_validate=[CombineArchiveContentFormat.OMEX_METADATA]) self.assertIn( 'The OMEX Metadata file at location `metadata.rdf` is invalid.', flatten_nested_list_of_strings(errors)) self.assertNotEqual(warnings, []) with mock.patch.dict('os.environ', { 'VALIDATE_OMEX_MANIFESTS': '0', 'VALIDATE_OMEX_METADATA': '0', }): errors, warnings = validate( archive, archive_dirname, formats_to_validate=[ CombineArchiveContentFormat.OMEX_METADATA ]) self.assertEqual(errors, []) self.assertEqual(warnings, []) os.remove(metadata_file)
def test_read_omex_meta_file_no_root(self): filename = self.NO_ROOT_FIXTURE metadata, errors, warnings = io.BiosimulationsOmexMetaReader().run(filename, working_dir=self.dir_name) self.assertEqual(metadata, None) self.assertIn('does not contain metadata', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, [])
def test_BiosimulationsOmexMetaReader_run(self): metadata, errors, warnings = io.BiosimulationsOmexMetaReader().run(self.FIXTURE, working_dir=self.dir_name) expected = [{ 'uri': '.', 'combine_archive_uri': 'http://omex-library.org/BioSim0001.omex', 'title': 'Name', 'abstract': 'Short summary', 'keywords': ['tag 1', 'tag 2'], 'thumbnails': ['./thumbnail.png'], 'description': 'Description', 'taxa': [ { 'uri': 'http://identifiers.org/taxonomy/9606', 'label': 'H**o sapiens', } ], 'encodes': [ { 'uri': 'http://identifiers.org/CL:0001057', 'label': 'myeloid dendritic cell, human', } ], 'sources': [ { 'uri': 'http://identifiers.org/github:lab/project', 'label': 'Tsur 2019 model source code', } ], 'predecessors': [ { 'uri': 'http://identifiers.org/biomodels.db:BIOMD0000000837', 'label': 'Hanson2016 - Toxicity Management in CAR T cell therapy for B-ALL', } ], 'references': [ { 'uri': 'http://identifiers.org/pubmed:1234', 'label': 'D Nadeau, C Marchand. Change in the kinetics of sulphacetamide tissue distribution in Walker tumor-bearing rats. Drug Metab Dispos 3(6): 565-76 (1975).', }, ], 'successors': [ { 'uri': 'http://identifiers.org/biomodels.db:BIOMD0000000839', 'label': 'Almeida2019 - Transcription-based circadian ...', } ], 'see_also': [ { 'uri': 'http://identifiers.org/biomodels.db:BIOMD0000000836', 'label': 'Radosavljevic2009_BioterroristAttack_PanicProtection_1', } ], 'identifiers': [ { 'uri': 'http://identifiers.org/biomodels.db:BIOMD0000000838', 'label': 'biomodels.db:BIOMD0000000838', } ], 'citations': [ { 'uri': 'http://identifiers.org/doi:10.1016/j.copbio.2017.12.013', 'label': ( 'Goldberg AP, Szigeti B, Chew YH, Sekar JA, Roth YD & Karr JR. ' 'Emerging whole-cell modeling principles and methods. ' 'Curr Opin Biotechnol 2018, 51:97-102.' ), }, { 'uri': 'http://identifiers.org/pubmed:29275251', 'label': ( 'Goldberg AP, Szigeti B, Chew YH, Sekar JA, Roth YD & Karr JR. ' 'Emerging whole-cell modeling principles and methods. ' 'Curr Opin Biotechnol 2018, 51:97-102.' ), } ], 'creators': [ { 'uri': 'http://identifiers.org/orcid:0000-0001-8254-4958', 'label': 'Jonathan Karr', } ], 'contributors': [ { 'uri': None, 'label': 'Name of person with no ORCID account', } ], 'license': { 'uri': 'http://identifiers.org/spdx:MIT', 'label': 'MIT', }, 'funders': [ { 'uri': 'http://identifiers.org/doi:10.13039/100000001', 'label': 'National Science Foundation', }, ], 'created': '2020-06-18', 'modified': ['2021-06-18'], 'other': [ { 'attribute': { 'uri': 'http://ontology.eil.utoronto.ca/icity/OM/temporalUnit', 'label': 'Temporal unit', }, 'value': { 'uri': 'http://www.w3.org/2006/time#second', 'label': 'second', }, }, ], }] for key in expected[0].keys(): self.assertEqual(metadata[0][key], expected[0][key], key) self.assertEqual(metadata, expected) self.assertEqual(errors, []) self.assertEqual(warnings, []) filename = os.path.join(self.FIXTURE_DIR, 'biosimulations-abbrev.rdf') metadata2, errors, warnings = io.BiosimulationsOmexMetaReader().run(filename, working_dir=self.dir_name) self.assertEqual(metadata2, metadata) filename = os.path.join(self.FIXTURE_DIR, 'abbrev.rdf') metadata, errors, warnings = io.BiosimulationsOmexMetaReader().run(filename, working_dir=self.dir_name) self.assertEqual(metadata[0]['title'], 'Name') self.assertEqual(metadata[0]['funders'], [ { 'uri': 'http://identifiers.org/doi:10.13039/100000001', 'label': 'National Science Foundation', }, ]) self.assertEqual(errors, []) self.assertEqual(warnings, []) md, errors, warnings = io.BiosimulationsOmexMetaReader().run( os.path.join(self.FIXTURE_DIR, 'biosimulations-with-file-annotations.rdf'), working_dir=self.dir_name) self.assertEqual(errors, []) self.assertEqual(warnings, []) self.assertEqual(len(md), 2) self.assertEqual(set(m['uri'] for m in md), set(['.', './sim.sedml/figure1'])) m = next(m for m in md if m['uri'] == './sim.sedml/figure1') self.assertEqual(m, { 'uri': './sim.sedml/figure1', 'combine_archive_uri': 'http://omex-library.org/BioSim0001.omex', 'title': None, 'abstract': None, 'keywords': [], 'thumbnails': [], 'description': None, 'taxa': [], 'encodes': [], 'sources': [], 'predecessors': [], 'references': [], 'successors': [], 'see_also': [], 'identifiers': [{ 'uri': 'http://identifiers.org/doi:10.1371/journal.pcbi.1008379.g001', 'label': 'Figure 1a', }], 'citations': [], 'creators': [], 'contributors': [], 'license': None, 'funders': [], 'created': None, 'modified': [], 'other': [ ], }) filename = os.path.join(self.FIXTURE_DIR, 'missing-required.rdf') metadata, errors, warnings = io.BiosimulationsOmexMetaReader().run(filename, working_dir=self.dir_name) self.assertIn('is required', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) filename = os.path.join(self.FIXTURE_DIR, 'missing-label.rdf') metadata, errors, warnings = io.BiosimulationsOmexMetaReader().run(filename, working_dir=self.dir_name) self.assertEqual(errors, []) self.assertIn('does not contain an rdf:label', flatten_nested_list_of_strings(warnings)) filename = os.path.join(self.FIXTURE_DIR, 'invalid-thumbnail-uri.rdf') metadata, errors, warnings = io.BiosimulationsOmexMetaReader().run(filename, working_dir=self.dir_name) self.assertIn('must begin with the URI', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) filename = os.path.join(self.FIXTURE_DIR, 'missing-thumbnail-uri.rdf') metadata, errors, warnings = io.BiosimulationsOmexMetaReader().run(filename, working_dir=self.dir_name) self.assertEqual(errors, []) self.assertIn('does not contain an URI', flatten_nested_list_of_strings(warnings)) filename = os.path.join(self.FIXTURE_DIR, 'missing-uri.rdf') metadata, errors, warnings = io.BiosimulationsOmexMetaReader().run(filename, working_dir=self.dir_name) self.assertEqual(errors, []) self.assertEqual(warnings, []) filename = os.path.join(self.FIXTURE_DIR, 'missing-label-2.rdf') metadata, errors, warnings = io.BiosimulationsOmexMetaReader().run(filename, working_dir=self.dir_name) self.assertEqual(errors, []) self.assertIn('does not contain an rdf:label', flatten_nested_list_of_strings(warnings)) filename = os.path.join(self.FIXTURE_DIR, 'too-many-objects.rdf') metadata, errors, warnings = io.BiosimulationsOmexMetaReader().run(filename, working_dir=self.dir_name) self.assertIn('should only contain one instance of predicate', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) filename = 'does not exist' metadata, errors, warnings = io.BiosimulationsOmexMetaReader().run(filename, working_dir=self.dir_name) self.assertEqual(metadata, None) self.assertIn('is not a file', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) filename = self.NO_ROOT_FIXTURE metadata, errors, warnings = io.BiosimulationsOmexMetaReader().run(filename, working_dir=self.dir_name) self.assertNotEqual(metadata, None) self.assertIn('Thumbnail URIs must begin with', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, [])
def test_validate_biosimulations_metadata_for_uri(self): config = Config( OMEX_METADATA_SCHEMA=data_model.OmexMetadataSchema.biosimulations) md, _, _ = read_omex_meta_file(self.FIXTURE, config=config) md = md[0] errors, warnings = validate_biosimulations_metadata_for_uri(md) self.assertEqual(errors, []) self.assertIn('thumbnails could not be validated', flatten_nested_list_of_strings(warnings)) errors, warnings = validate_biosimulations_metadata_for_uri( md, working_dir=self.dir_name) self.assertIn('is not a file', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) shutil.copyfile( os.path.join(self.FIXTURES_DIR, 'images', 'PNG_transparency_demonstration_1.png'), os.path.join(self.dir_name, 'thumbnail.png')) errors, warnings = validate_biosimulations_metadata_for_uri( md, working_dir=self.dir_name) self.assertEqual(errors, []) self.assertEqual(warnings, []) shutil.copyfile( os.path.join(self.FIXTURES_DIR, 'images', 'PNG_transparency_demonstration_1.png'), os.path.join(self.dir_name, 'thumbnail.png')) archive = CombineArchive(contents=[ CombineArchiveContent( location='thumbnail.png', format=CombineArchiveContentFormat.PNG.value, ), ]) errors, warnings = validate_biosimulations_metadata_for_uri( md, validate_minimal_metadata=True, archive=archive, working_dir=self.dir_name) self.assertEqual(errors, []) self.assertEqual(warnings, []) archive.contents[0].format = CombineArchiveContentFormat.PDF.value errors, warnings = validate_biosimulations_metadata_for_uri( md, validate_minimal_metadata=True, archive=archive, working_dir=self.dir_name) self.assertNotEqual(errors, []) self.assertEqual(warnings, []) md2 = copy.deepcopy(md) md2['title'] = None errors, warnings = validate_biosimulations_metadata_for_uri( md2, validate_minimal_metadata=True, working_dir=self.dir_name) self.assertIn('is required', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) md2 = copy.deepcopy(md) md2['creators'][0]['uri'] = 'xyz' errors, warnings = validate_biosimulations_metadata_for_uri( md2, validate_minimal_metadata=True, working_dir=self.dir_name) self.assertIn('is not a valid URI', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) md2 = copy.deepcopy(md) md2['created'] = 'xyz' errors, warnings = validate_biosimulations_metadata_for_uri( md2, validate_minimal_metadata=True, working_dir=self.dir_name) self.assertIn('is not a valid date', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) md2 = copy.deepcopy(md) md2['modified'].append('xyz') errors, warnings = validate_biosimulations_metadata_for_uri( md2, validate_minimal_metadata=True, working_dir=self.dir_name) self.assertIn('is not a valid date', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) md2 = copy.deepcopy(md) md2['creators'][0]['uri'] = 'http://identifiers.org/pubmed:1234' errors, warnings = validate_biosimulations_metadata_for_uri( md2, validate_minimal_metadata=True, working_dir=self.dir_name) self.assertEqual(errors, []) self.assertEqual(warnings, []) md2 = copy.deepcopy(md) md2['creators'][0]['uri'] = 'http://identifiers.org/pubmed/1234' errors, warnings = validate_biosimulations_metadata_for_uri( md2, validate_minimal_metadata=True, working_dir=self.dir_name) self.assertEqual(errors, []) self.assertEqual(warnings, []) md2 = copy.deepcopy(md) md2['creators'][0]['uri'] = 'http://identifiers.org/PubMed:1234' errors, warnings = validate_biosimulations_metadata_for_uri( md2, validate_minimal_metadata=True, working_dir=self.dir_name) self.assertEqual(errors, []) self.assertEqual(warnings, []) md2 = copy.deepcopy(md) md2['creators'][0]['uri'] = 'http://identifiers.org/ncbi/pubmed:1234' errors, warnings = validate_biosimulations_metadata_for_uri( md2, validate_minimal_metadata=True, working_dir=self.dir_name) self.assertEqual(errors, []) self.assertEqual(warnings, []) md2 = copy.deepcopy(md) md2['creators'][0]['uri'] = 'http://identifiers.org/NCBI/pubmed:1234' errors, warnings = validate_biosimulations_metadata_for_uri( md2, validate_minimal_metadata=True, working_dir=self.dir_name) self.assertEqual(errors, []) self.assertEqual(warnings, []) md2 = copy.deepcopy(md) md2['creators'][0][ 'uri'] = 'http://identifiers.org/not-a-namespace:invalid' errors, warnings = validate_biosimulations_metadata_for_uri( md2, validate_minimal_metadata=True, working_dir=self.dir_name) self.assertIn('is not a valid prefix', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) md2 = copy.deepcopy(md) md2['creators'][0]['uri'] = 'http://identifiers.org/pubmed:invalid' errors, warnings = validate_biosimulations_metadata_for_uri( md2, validate_minimal_metadata=True, working_dir=self.dir_name) self.assertIn('is not valid for', flatten_nested_list_of_strings(errors)) self.assertIn('not a valid Identifiers.org identifier', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) md2 = copy.deepcopy(md) md2['creators'][0]['uri'] = 'http://identifiers.org/ncbi:pubmed:1234' errors, warnings = validate_biosimulations_metadata_for_uri( md2, validate_minimal_metadata=True, working_dir=self.dir_name) self.assertIn('is not a valid prefix', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) md2 = copy.deepcopy(md) md2['thumbnails'][0] = 'x' errors, warnings = validate_biosimulations_metadata_for_uri( md2, validate_minimal_metadata=True, working_dir=self.dir_name) self.assertIn('is not a file', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) md2 = copy.deepcopy(md) errors, warnings = validate_biosimulations_metadata_for_uri( md2, validate_minimal_metadata=True, working_dir=self.dir_name, archive=CombineArchive(contents=[ CombineArchiveContent( location=os.path.relpath(md2['thumbnails'][0], '.'), format=CombineArchiveContentFormat.TEXT.value, ) ])) self.assertIn('must be one of the following', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) md2 = copy.deepcopy(md) md2['created'] = 'x' errors, warnings = validate_biosimulations_metadata_for_uri( md2, validate_minimal_metadata=True, working_dir=self.dir_name) self.assertIn('not a valid date', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) md2 = copy.deepcopy(md) md2['modified'][0] = 'x' errors, warnings = validate_biosimulations_metadata_for_uri( md2, validate_minimal_metadata=True, working_dir=self.dir_name) self.assertIn('not a valid date', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, [])
def handler(body, file=None): ''' Get the manifest of a COMBINE/OMEX archive Args: body (:obj:`dict`): dictionary with keys * ``url`` whose value has schema ``Url`` with the URL for a COMBINE/OMEX archive or a manifest for a COMBINE/OMEX archive file (:obj:`werkzeug.datastructures.FileStorage`, optional): COMBINE/OMEX archive or OMEX manifest file Returns: ``CombineArchive``: manifest of the COMBINE/OMEX archive ''' archive_or_manifest_file = file archive_or_manifest_url = body.get('url', None) if archive_or_manifest_url and archive_or_manifest_file: raise BadRequestException( title='Only one of `file` or `url` can be used at a time.', instance=ValueError(), ) if not archive_or_manifest_url and not archive_or_manifest_file: raise BadRequestException( title='One of `file` or `url` must be used.', instance=ValueError(), ) # create temporary working directory temp_dirname = get_temp_dir() archive_or_manifest_filename = os.path.join(temp_dirname, 'archive.omex') manifest_filename = os.path.join(temp_dirname, 'manifest.xml') # get COMBINE/OMEX archive or manifest if archive_or_manifest_file: archive_or_manifest_file.save(archive_or_manifest_filename) else: try: response = requests.get(archive_or_manifest_url) response.raise_for_status() except requests.exceptions.RequestException as exception: title = 'File could not be loaded from `{}`'.format( archive_or_manifest_url) raise BadRequestException( title=title, instance=exception, ) # save archive to local temporary file with open(archive_or_manifest_filename, 'wb') as file: file.write(response.content) # read archive is_archive = False try: with zipfile.ZipFile(archive_or_manifest_filename, 'r') as zip_file: is_archive = True zip_file.extract('manifest.xml', temp_dirname) except zipfile.BadZipFile: pass except KeyError as exception: raise BadRequestException( title='COMBINE/OMEX archive does not contain a manifest.', instance=exception) if not is_archive: manifest_filename = archive_or_manifest_filename reader = CombineArchiveReader() contents = reader.read_manifest(manifest_filename, archive_or_manifest_filename) if reader.errors: raise BadRequestException( title= 'File is not a valid manifest or a COMBINE/OMEX which contains a valid manifest.\n {}' .format( flatten_nested_list_of_strings(reader.errors).replace( '\n', '\n ')), instance=ValueError()) contents_specs = [] for content in contents: content_specs = { '_type': 'CombineArchiveManifestContent', 'location': { '_type': 'CombineArchiveManifestLocation', 'path': content.location, 'value': { '_type': 'CombineArchiveContentFile', 'filename': os.path.relpath(content.location, '.'), }, }, 'format': content.format, 'master': content.master, } contents_specs.append(content_specs) # format response response = {'_type': 'CombineArchiveManifest', 'contents': contents_specs} # return reponse return response
def test(self): filename = os.path.join(self.FIXTURE_DIRNAME, 'wilson-cowan.ode') errors, warnings, model = validation.validate_model(filename) self.assertEqual(errors, []) self.assertEqual(warnings, []) parameters = collections.OrderedDict([ ('aee', 10), ('aie', 8), ('aei', 12), ('aii', 3), ('ze', .2), ('zi', 4), ('tau', 1), ('ie0', 0.0), ('ie1', 0.0), ('w', 0.25), ('ii0', 0.0), ('ii1', 0.0), ]) initial_conditions = collections.OrderedDict([ ('U', .1), ('V', .05), ]) simulation_method = { 'total': '40', } plot = { 'elements': { 1: { 'x': 'U', 'y': 'V', }, }, 'xlo': -.1, 'xhi': 1., 'ylo': -.1, 'yhi': 1., } self.assertEqual(list(model['parameters'].keys()), list(parameters.keys())) self.assertEqual(model['parameters'], parameters) self.assertEqual(model['simulation_method'], simulation_method) self.assertEqual(model['plot'], plot) self.assertEqual( model, { 'parameters': parameters, 'initial_conditions': initial_conditions, 'sets': {}, 'auxiliary_variables': collections.OrderedDict(), 'simulation_method': simulation_method, 'range': None, 'plot': plot, }) self.assertEqual(model['initial_conditions'], initial_conditions) filename = os.path.join(self.FIXTURE_DIRNAME, 'wilson-cowan-modified.ode') errors, warnings, model = validation.validate_model(filename) self.assertEqual(errors, []) self.assertEqual(warnings, []) self.assertEqual(model['simulation_method'], { 'total': '130', 'njmp': '20', }) self.assertEqual( model['plot'], { 'elements': { 1: { 'x': 'U', 'y': 'V', }, }, 'xlo': -.1, 'xhi': 1., 'ylo': -.1, 'yhi': 1., 'axes': 2, }) filename = os.path.join(self.FIXTURE_DIRNAME, 'wilson-cowan-auxiliary-variables.ode') errors, warnings, model = validation.validate_model(filename) self.assertEqual(errors, []) self.assertEqual(warnings, []) self.assertEqual( model['auxiliary_variables'], collections.OrderedDict({ 'DV': "-u+f(aee*u-aie*v-ze+i_e(t))", })) filename = None errors, warnings, model = validation.validate_model(filename) self.assertIn('is not a path', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) self.assertEqual(model, None) filename = os.path.join(self.FIXTURE_DIRNAME, 'not exist.ode') errors, warnings, model = validation.validate_model(filename) self.assertIn('does not exist', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) self.assertEqual(model, None) filename = os.path.join(self.FIXTURE_DIRNAME, 'wilson-cowan-invalid.ode') errors, warnings, model = validation.validate_model(filename) self.assertIn('is not a valid XPP', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) self.assertEqual(model, None) filename = os.path.join(self.FIXTURE_DIRNAME, 'wilson-cowan-invalid.ode') return_value_1 = mock.Mock( returncode=1, stdout=mock.Mock(decode=lambda errors: 'Error message', ), ) with mock.patch('subprocess.run', return_value=return_value_1): errors, warnings, model = validation.validate_model(filename) self.assertIn('is not a valid XPP file', flatten_nested_list_of_strings(errors)) self.assertIn('Error message', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) self.assertEqual(model, None) filename = os.path.join(self.FIXTURE_DIRNAME, 'wilson-cowan-modified-3.ode') errors, warnings, model = validation.validate_model(filename) self.assertIn('T0 must be a float', flatten_nested_list_of_strings(errors)) self.assertIn('TOTAL must be a float', flatten_nested_list_of_strings(errors)) self.assertIn('DT must be a float', flatten_nested_list_of_strings(errors)) self.assertIn('NJMP must be a positive integer', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) self.assertNotEqual(model, None) filename = os.path.join(self.FIXTURE_DIRNAME, 'wilson-cowan-modified-4.ode') errors, warnings, model = validation.validate_model(filename) self.assertIn('T0 must be a float', flatten_nested_list_of_strings(errors)) self.assertIn('TOTAL must be a float', flatten_nested_list_of_strings(errors)) self.assertIn('DT must be a float', flatten_nested_list_of_strings(errors)) self.assertIn('NJMP must be a positive integer', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) self.assertNotEqual(model, None) filename = os.path.join(self.FIXTURE_DIRNAME, 'wilson-cowan-modified-5.ode') errors, warnings, model = validation.validate_model(filename) self.assertIn('Number of steps must be an integer', flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) self.assertNotEqual(model, None) filename = os.path.join(self.FIXTURE_DIRNAME, 'BIOMD0000000001.ode') errors, warnings, model = validation.validate_model(filename) self.assertEqual(errors, []) self.assertIn("I' is a duplicate name", flatten_nested_list_of_strings(warnings)) self.assertEqual( model['simulation_method'], { 'delay': '50', 'meth': 'cvode', 'tol': '1e-6', 'atol': '1e-8', 'bound': '40000', 'total': '200', })
def test(self): # 1 model errors, warnings, _ = validate_model( os.path.join(self.FIXTURE_DIR, 'albrecht_colegrove_friel_2002.xml')) self.assertEqual(errors, []) self.assertEqual(warnings, []) errors, warnings, _ = validate_model( os.path.join(self.FIXTURE_DIR, 'albrecht_colegrove_friel_2002-error.xml')) self.assertIn("has extra content: units2", flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) # 1.1 model errors, warnings, _ = validate_model( os.path.join(self.FIXTURE_DIR, 'parameters-1.1.cellml')) self.assertEqual(errors, []) self.assertIn("not available for CellML 1.1", flatten_nested_list_of_strings(warnings)) # 2.0 model errors, warnings, _ = validate_model( os.path.join(self.FIXTURE_DIR, 'version2.xml')) self.assertEqual(errors, []) self.assertEqual(warnings, []) errors, warnings, _ = validate_model( os.path.join(self.FIXTURE_DIR, 'version2-with-imports.xml')) self.assertEqual(errors, []) self.assertEqual(warnings, []) errors, warnings, _ = validate_model( os.path.join(self.FIXTURE_DIR, 'version2-missing-imports.xml')) self.assertIn("the file could not be opened", flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) # 2.0 error: invalid namespace errors, warnings, _ = validate_model( os.path.join(self.FIXTURE_DIR, 'invalid_namespace.xml')) self.assertIn("default namespace must be", flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) errors, warnings, _ = validate_model( os.path.join(self.FIXTURE_DIR, 'not_a_path.xml')) self.assertIn("is not a file", flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) errors, warnings, _ = validate_model( os.path.join(self.FIXTURE_DIR, 'invalid_cellml_2.0.xml')) self.assertIn("Start tag expected", flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) return_value = mock.Mock(getroot=lambda: mock.Mock(nsmap=mock.Mock( get=lambda x, y: 'http://www.cellml.org/cellml/2.0#'))) with mock.patch('lxml.etree.parse', return_value=return_value): errors, warnings, _ = validate_model( os.path.join(self.FIXTURE_DIR, 'invalid_cellml_2.0.xml')) self.assertIn("Start tag expected", flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, []) errors, warnings, _ = validate_model( os.path.join(self.FIXTURE_DIR, 'missing-attribute.xml')) self.assertIn("does not have a valid name attribute", flatten_nested_list_of_strings(errors)) self.assertEqual(warnings, [])
def test_error_handling(self): os.remove(os.path.join(self.tmp_dir, 'thumbnail.png')) archive = CombineArchive() errors, warnings = validate(archive, self.tmp_dir) self.assertEqual(len(errors), 1) self.assertEqual(len(errors[0]), 1) self.assertIn('must have at least one content element', errors[0][0]) self.assertEqual(len(warnings), 1) self.assertEqual(len(warnings[0]), 1) self.assertIn('does not contain any SED-ML files', warnings[0][0]) archive = CombineArchive(contents=[ None, ]) errors, warnings = validate(archive, self.tmp_dir) self.assertEqual(len(errors), 1) self.assertEqual(len(warnings), 1) self.assertIn('must be an instance of', flatten_nested_list_of_strings(errors)) self.assertIn('does not contain any SED-ML files', flatten_nested_list_of_strings(warnings)) archive = CombineArchive(contents=[ CombineArchiveContent(), ]) errors, warnings = validate(archive, self.tmp_dir) self.assertEqual(len(errors), 1) self.assertEqual(len(warnings), 1) self.assertIn('must have a location', flatten_nested_list_of_strings(errors)) self.assertIn('must have a format', flatten_nested_list_of_strings(errors)) self.assertIn('does not contain any SED-ML files', flatten_nested_list_of_strings(warnings)) archive = CombineArchive(contents=[ CombineArchiveContent( location='plain.txt', format='plain/text', ), ]) errors, warnings = validate(archive, self.tmp_dir) self.assertEqual(len(errors), 1) self.assertEqual(len(warnings), 1) self.assertIn('is not a file', flatten_nested_list_of_strings(errors)) self.assertIn('does not contain any SED-ML files', flatten_nested_list_of_strings(warnings)) with open(os.path.join(self.tmp_dir, 'sim.sedml'), 'w') as file: pass archive = CombineArchive(contents=[ CombineArchiveContent( location='sim.sedml', format=CombineArchiveContentFormat.SED_ML, ), ]) errors, warnings = validate(archive, self.tmp_dir) self.assertEqual(len(errors), 1) self.assertEqual(warnings, []) self.assertIn('is invalid', flatten_nested_list_of_strings(errors)) archive = CombineArchive(contents=[ CombineArchiveContent( location='sim.sedml', format=CombineArchiveContentFormat.SED_ML, ), ]) with mock.patch.object(SedmlSimulationReader, 'run', side_effect=ValueError('other error')): with self.assertRaisesRegex(ValueError, 'other error'): validate(archive, self.tmp_dir) def side_effect(self, filename, validate_models_with_languages=False, config=None): self.warnings = [['my warning']] with mock.patch.object(SedmlSimulationReader, 'run', side_effect): errors, warnings = validate(archive, self.tmp_dir) self.assertEqual(errors, []) self.assertEqual(len(warnings), 1) self.assertIn('may be invalid', flatten_nested_list_of_strings(warnings)) self.assertIn('my warning', flatten_nested_list_of_strings(warnings))